diff --git a/promql/engine_extra.go b/promql/engine_extra.go index a51bfef891..42930dd955 100644 --- a/promql/engine_extra.go +++ b/promql/engine_extra.go @@ -13,6 +13,11 @@ func findPathRange(path []parser.Node, eRanges []evalRange) time.Duration { depth int ) for _, r := range eRanges { + // If the prefix is longer then it can't be the parent of `child` + if len(r.Prefix) > len(path) { + continue + } + // Check if we are a child child := true for i, p := range r.Prefix { diff --git a/promql/engine_extra_test.go b/promql/engine_extra_test.go new file mode 100644 index 0000000000..d1070dca3c --- /dev/null +++ b/promql/engine_extra_test.go @@ -0,0 +1,56 @@ +package promql + +import ( + "fmt" + "reflect" + "strconv" + "testing" + "time" + + "github.com/prometheus/prometheus/promql/parser" +) + +type StubNode struct { + start, end int +} + +func (s StubNode) String() string { + return fmt.Sprintf("[%d,%d]", s.start, s.end) +} + +func (s StubNode) PositionRange() parser.PositionRange { + return parser.PositionRange{ + Start: parser.Pos(s.start), + End: parser.Pos(s.end), + } +} + +func TestFindPathRange(t *testing.T) { + tests := []struct { + path []parser.Node + eRanges []evalRange + out time.Duration + }{ + // Test a case where the evalRange is longer than the path + { + path: []parser.Node{StubNode{0, 1}}, + eRanges: []evalRange{ + evalRange{ + Prefix: []parser.PositionRange{ + parser.PositionRange{parser.Pos(0), parser.Pos(1)}, + parser.PositionRange{parser.Pos(1), parser.Pos(3)}, + }, + }, + }, + }, + } + + for i, test := range tests { + t.Run(strconv.Itoa(i), func(t *testing.T) { + out := findPathRange(test.path, test.eRanges) + if !reflect.DeepEqual(out, test.out) { + t.Fatalf("Mismatch in test output expected=%#v actual=%#v", test.out, out) + } + }) + } +}