<commit_before>package expr

import (
	"strconv"
	"testing"

	"github.com/grafana/metrictank/api/models"
	"github.com/grafana/metrictank/test"
	"github.com/raintank/schema"
)

func getNewSubstr(in []models.Series, start, stop int64) *FuncSubstr {
	f := NewSubstr()
	s := f.(*FuncSubstr)
	s.in = NewMock(in)
	s.start = start
	s.stop = stop
	return s
}

func TestSubstrNoArgs(t *testing.T) {
	f := getNewSubstr(
		[]models.Series{
			{
				Interval:   10,
				QueryPatt:  "a.b.c.d.*",
				Target:     "a.b.c.d.e",
				Datapoints: getCopy(a),
			},
		},
		0,
		0,
	)
	out := []models.Series{
		{
			Interval:   10,
			QueryPatt:  "a.b.c.d.*",
			Target:     "a.b.c.d.e",
			Datapoints: getCopy(a),
		},
	}

	got, err := f.Exec(make(map[Req][]models.Series))
	if err := equalOutput(out, got, nil, err); err != nil {
		t.Fatal(err)
	}
}

func TestSubstrStart(t *testing.T) {
	f := getNewSubstr(
		[]models.Series{
			{
				Interval:   10,
				QueryPatt:  "a.b.c.d.*",
				Target:     "a.b.c.d.e",
				Datapoints: getCopy(a),
			},
		},
		2,
		0,
	)
	out := []models.Series{
		{
			Interval:   10,
			QueryPatt:  "a.b.c.d.*",
			Target:     "c.d.e",
			Datapoints: getCopy(a),
		},
	}

	got, err := f.Exec(make(map[Req][]models.Series))
	if err := equalOutput(out, got, nil, err); err != nil {
		t.Fatal(err)
	}
}

func TestSubstrStartStop(t *testing.T) {
	f := getNewSubstr(
		[]models.Series{
			{
				Interval:   10,
				QueryPatt:  "a.b.c.d.*",
				Target:     "a.b.c.d.e",
				Datapoints: getCopy(a),
			},
		},
		2,
		4,
	)
	out := []models.Series{
		{
			Interval:   10,
			QueryPatt:  "a.b.c.d.*",
			Target:     "c.d",
			Datapoints: getCopy(a),
		},
	}

	got, err := f.Exec(make(map[Req][]models.Series))
	if err := equalOutput(out, got, nil, err); err != nil {
		t.Fatal(err)
	}
}

func TestSubstrWithFuncs(t *testing.T) {
	f := getNewSubstr(
		[]models.Series{
			{
				Interval:   10,
				QueryPatt:  "foo(bar(a.b.c.d.*,foo))",
				Target:     "foo(bar(a.b.c.d.e,foo))",
				Datapoints: getCopy(a),
			},
		},
		2,
		4,
	)
	out := []models.Series{
		{
			Interval:   10,
			QueryPatt:  "foo(bar(a.b.c.d.*,foo))",
			Target:     "c.d",
			Datapoints: getCopy(a),
		},
	}

	got, err := f.Exec(make(map[Req][]models.Series))
	if err := equalOutput(out, got, nil, err); err != nil {
		t.Fatal(err)
	}
}

func BenchmarkSubstr10k_1NoNulls(b *testing.B) {
	benchmarkSubstr(b, 1, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkSubstr10k_10NoNulls(b *testing.B) {
	benchmarkSubstr(b, 10, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkSubstr10k_100NoNulls(b *testing.B) {
	benchmarkSubstr(b, 100, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkSubstr10k_1000NoNulls(b *testing.B) {
	benchmarkSubstr(b, 1000, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkSubstr10k_1SomeSeriesHalfNulls(b *testing.B) {
	benchmarkSubstr(b, 1, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkSubstr10k_10SomeSeriesHalfNulls(b *testing.B) {
	benchmarkSubstr(b, 10, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkSubstr10k_100SomeSeriesHalfNulls(b *testing.B) {
	benchmarkSubstr(b, 100, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkSubstr10k_1000SomeSeriesHalfNulls(b *testing.B) {
	benchmarkSubstr(b, 1000, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkSubstr10k_1AllSeriesHalfNulls(b *testing.B) {
	benchmarkSubstr(b, 1, test.RandFloatsWithNulls10k, test.RandFloatsWithNulls10k)<commit_msg>use new testing paradigm<commit_after>package expr

import (
	"strconv"
	"testing"

	"github.com/grafana/metrictank/api/models"
	"github.com/grafana/metrictank/test"
	"github.com/raintank/schema"
)

func TestSubstrNoArgs(t *testing.T) {
	input := []models.Series{
		{
			Interval:   10,
			QueryFrom:  10,
			QueryTo:    61,
			QueryPatt:  "a.b.c.d.*",
			Target:     "a.b.c.d.e",
			Datapoints: getCopy(a),
		},
	}
	exp := []models.Series{
		{
			Interval:   10,
			QueryFrom:  10,
			QueryTo:    61,
			QueryPatt:  "a.b.c.d.*",
			Target:     "a.b.c.d.e",
			Datapoints: getCopy(a),
		},
	}
	testSubstr("TestSubstrNoArgs", input, exp, 0, 0, t)
}

func TestSubstrStart(t *testing.T) {
	input := []models.Series{
		{
			Interval:   10,
			QueryFrom:  10,
			QueryTo:    61,
			QueryPatt:  "a.b.c.d.*",
			Target:     "a.b.c.d.e",
			Datapoints: getCopy(a),
		},
	}
	exp := []models.Series{
		{
			Interval:   10,
			QueryFrom:  10,
			QueryTo:    61,
			QueryPatt:  "a.b.c.d.*",
			Target:     "c.d.e",
			Datapoints: getCopy(a),
		},
	}
	testSubstr("TestSubstrStart", input, exp, 2, 0, t)
}

func TestSubstrStartStop(t *testing.T) {
	input := []models.Series{
		{
			Interval:   10,
			QueryFrom:  10,
			QueryTo:    61,
			QueryPatt:  "a.b.c.d.*",
			Target:     "a.b.c.d.e",
			Datapoints: getCopy(a),
		},
	}
	exp := []models.Series{
		{
			Interval:   10,
			QueryFrom:  10,
			QueryTo:    61,
			QueryPatt:  "a.b.c.d.*",
			Target:     "c.d",
			Datapoints: getCopy(a),
		},
	}
	testSubstr("TestSubstrStartStop", input, exp, 2, 4, t)
}

func TestSubstrWithFuncs(t *testing.T) {
	input := []models.Series{
		{
			Interval:   10,
			QueryFrom:  10,
			QueryTo:    61,
			QueryPatt:  "foo(bar(a.b.c.d.*,foo))",
			Target:     "foo(bar(a.b.c.d.e,foo))",
			Datapoints: getCopy(a),
		},
	}
	exp := []models.Series{
		{
			Interval:   10,
			QueryFrom:  10,
			QueryTo:    61,
			QueryPatt:  "foo(bar(a.b.c.d.*,foo))",
			Target:     "c.d",
			Datapoints: getCopy(a),
		},
	}
	testSubstr("TestSubstrWithFuncs", input, exp, 2, 4, t)
}

func testSubstr(name string, in []models.Series, out []models.Series, start, stop int64, t *testing.T) {
	f := NewSubstr()
	substr := f.(*FuncSubstr)
	substr.in = NewMock(in)
	substr.start = start
	substr.stop = stop

	inputCopy := models.SeriesCopy(in) // to later verify that it is unchanged

	dataMap := initDataMap(in)

	got, err := f.Exec(dataMap)
	if err := equalOutput(out, got, nil, err); err != nil {
		t.Fatalf("Case %s: %s", name, err)
	}

	t.Run("DidNotModifyInput", func(t *testing.T) {
		if err := equalOutput(inputCopy, in, nil, nil); err != nil {
			t.Fatalf("Case %s: Input was modified, err = %s", name, err)
		}
	})

	t.Run("DoesNotDoubleReturnPoints", func(t *testing.T) {
		if err := dataMap.CheckForOverlappingPoints(); err != nil {
			t.Fatalf("Case %s: Point slices in datamap overlap, err = %s", name, err)
		}
	})
	t.Run("OutputIsCanonical", func(t *testing.T) {
		for i, s := range got {
			if !s.IsCanonical() {
				t.Fatalf("Case %s: output series %d is not canonical: %v", name, i, s)
			}
		}
	})
}

func BenchmarkSubstr10k_1NoNulls(b *testing.B) {
	benchmarkSubstr(b, 1, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkSubstr10k_10NoNulls(b *testing.B) {
	benchmarkSubstr(b, 10, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkSubstr10k_100NoNulls(b *testing.B) {
	benchmarkSubstr(b, 100, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkSubstr10k_1000NoNulls(b *testing.B) {
	benchmarkSubstr(b, 1000, test.RandFloats10k, test.RandFloats10k)
}
func BenchmarkSubstr10k_1SomeSeriesHalfNulls(b *testing.B) {
	benchmarkSubstr(b, 1, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkSubstr10k_10SomeSeriesHalfNulls(b *testing.B) {
	benchmarkSubstr(b, 10, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkSubstr10k_100SomeSeriesHalfNulls(b *testing.B) {
	benchmarkSubstr(b, 100, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkSubstr10k_1000SomeSeriesHalfNulls(b *testing.B) {
	benchmarkSubstr(b, 1000, test.RandFloats10k, test.RandFloatsWithNulls10k)
}
func BenchmarkSubstr10k_1AllSeriesHalfNulls(b *testing.B) {
	benchmarkSubstr(b, 1, test.RandFloatsWithNulls10k, test.RandFloatsWithNulls10k)
{'fraction_non_alphanumeric': 0.16664503569110967, 'fraction_numerical': 0.03582089552238806, 'mean_word_length': 3.5951103160405484, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1647498', 'n_tokens_mistral': 3876, 'n_tokens_neox': 3373, 'n_words': 573}