Selaa lähdekoodia

Expose helper string->index logic for profile.Profile

Vance Lankhaar 8 vuotta sitten
vanhempi
commit
058580598d
5 muutettua tiedostoa jossa 174 lisäystä ja 46 poistoa
  1. 0
    44
      internal/driver/commands.go
  2. 1
    1
      internal/driver/driver.go
  3. 9
    1
      internal/driver/interactive.go
  4. 64
    0
      profile/index.go
  5. 100
    0
      profile/index_test.go

+ 0
- 44
internal/driver/commands.go Näytä tiedosto

@@ -28,7 +28,6 @@ import (
28 28
 
29 29
 	"github.com/google/pprof/internal/plugin"
30 30
 	"github.com/google/pprof/internal/report"
31
-	"github.com/google/pprof/profile"
32 31
 	"github.com/google/pprof/third_party/svg"
33 32
 )
34 33
 
@@ -456,49 +455,6 @@ func invokeVisualizer(format PostProcessor, suffix string, visualizers []string)
456 455
 	}
457 456
 }
458 457
 
459
-// locateSampleIndex returns the appropriate index for a value of sample index.
460
-// If numeric, it returns the number, otherwise it looks up the text in the
461
-// profile sample types.
462
-func locateSampleIndex(p *profile.Profile, sampleIndex string) (int, error) {
463
-	if sampleIndex == "" {
464
-		if dst := p.DefaultSampleType; dst != "" {
465
-			for i, t := range sampleTypes(p) {
466
-				if t == dst {
467
-					return i, nil
468
-				}
469
-			}
470
-		}
471
-		// By default select the last sample value
472
-		return len(p.SampleType) - 1, nil
473
-	}
474
-	if i, err := strconv.Atoi(sampleIndex); err == nil {
475
-		if i < 0 || i >= len(p.SampleType) {
476
-			return 0, fmt.Errorf("sample_index %s is outside the range [0..%d]", sampleIndex, len(p.SampleType)-1)
477
-		}
478
-		return i, nil
479
-	}
480
-
481
-	// Remove the inuse_ prefix to support legacy pprof options
482
-	// "inuse_space" and "inuse_objects" for profiles containing types
483
-	// "space" and "objects".
484
-	noInuse := strings.TrimPrefix(sampleIndex, "inuse_")
485
-	for i, t := range p.SampleType {
486
-		if t.Type == sampleIndex || t.Type == noInuse {
487
-			return i, nil
488
-		}
489
-	}
490
-
491
-	return 0, fmt.Errorf("sample_index %q must be one of: %v", sampleIndex, sampleTypes(p))
492
-}
493
-
494
-func sampleTypes(p *profile.Profile) []string {
495
-	types := make([]string, len(p.SampleType))
496
-	for i, t := range p.SampleType {
497
-		types[i] = t.Type
498
-	}
499
-	return types
500
-}
501
-
502 458
 // variables describe the configuration parameters recognized by pprof.
503 459
 type variables map[string]*variable
504 460
 

+ 1
- 1
internal/driver/driver.go Näytä tiedosto

@@ -258,7 +258,7 @@ func sampleFormat(p *profile.Profile, sampleIndex string, mean bool) (value, mea
258 258
 	if len(p.SampleType) == 0 {
259 259
 		return nil, nil, nil, fmt.Errorf("profile has no samples")
260 260
 	}
261
-	index, err := locateSampleIndex(p, sampleIndex)
261
+	index, err := p.SampleIndexByName(sampleIndex)
262 262
 	if err != nil {
263 263
 		return nil, nil, nil, err
264 264
 	}

+ 9
- 1
internal/driver/interactive.go Näytä tiedosto

@@ -69,7 +69,7 @@ func interactive(p *profile.Profile, o *plugin.Options) error {
69 69
 				if v := pprofVariables[name]; v != nil {
70 70
 					if name == "sample_index" {
71 71
 						// Error check sample_index=xxx to ensure xxx is a valid sample type.
72
-						index, err := locateSampleIndex(p, value)
72
+						index, err := p.SampleIndexByName(value)
73 73
 						if err != nil {
74 74
 							o.UI.PrintErr(err)
75 75
 							continue
@@ -161,6 +161,14 @@ func profileShortcuts(p *profile.Profile) shortcuts {
161 161
 	return s
162 162
 }
163 163
 
164
+func sampleTypes(p *profile.Profile) []string {
165
+	types := make([]string, len(p.SampleType))
166
+	for i, t := range p.SampleType {
167
+		types[i] = t.Type
168
+	}
169
+	return types
170
+}
171
+
164 172
 func printCurrentOptions(p *profile.Profile, ui plugin.UI) {
165 173
 	var args []string
166 174
 	type groupInfo struct {

+ 64
- 0
profile/index.go Näytä tiedosto

@@ -0,0 +1,64 @@
1
+// Copyright 2016 Google Inc. All Rights Reserved.
2
+//
3
+// Licensed under the Apache License, Version 2.0 (the "License");
4
+// you may not use this file except in compliance with the License.
5
+// You may obtain a copy of the License at
6
+//
7
+//     http://www.apache.org/licenses/LICENSE-2.0
8
+//
9
+// Unless required by applicable law or agreed to in writing, software
10
+// distributed under the License is distributed on an "AS IS" BASIS,
11
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+// See the License for the specific language governing permissions and
13
+// limitations under the License.
14
+
15
+package profile
16
+
17
+import (
18
+	"fmt"
19
+	"strconv"
20
+	"strings"
21
+)
22
+
23
+// SampleIndexByName returns the appropriate index for a value of sample index.
24
+// If numeric, it returns the number, otherwise it looks up the text in the
25
+// profile sample types.
26
+func (p *Profile) SampleIndexByName(sampleIndex string) (int, error) {
27
+	if sampleIndex == "" {
28
+		if dst := p.DefaultSampleType; dst != "" {
29
+			for i, t := range sampleTypes(p) {
30
+				if t == dst {
31
+					return i, nil
32
+				}
33
+			}
34
+		}
35
+		// By default select the last sample value
36
+		return len(p.SampleType) - 1, nil
37
+	}
38
+	if i, err := strconv.Atoi(sampleIndex); err == nil {
39
+		if i < 0 || i >= len(p.SampleType) {
40
+			return 0, fmt.Errorf("sample_index %s is outside the range [0..%d]", sampleIndex, len(p.SampleType)-1)
41
+		}
42
+		return i, nil
43
+	}
44
+
45
+	// Remove the inuse_ prefix to support legacy pprof options
46
+	// "inuse_space" and "inuse_objects" for profiles containing types
47
+	// "space" and "objects".
48
+	noInuse := strings.TrimPrefix(sampleIndex, "inuse_")
49
+	for i, t := range p.SampleType {
50
+		if t.Type == sampleIndex || t.Type == noInuse {
51
+			return i, nil
52
+		}
53
+	}
54
+
55
+	return 0, fmt.Errorf("sample_index %q must be one of: %v", sampleIndex, sampleTypes(p))
56
+}
57
+
58
+func sampleTypes(p *Profile) []string {
59
+	types := make([]string, len(p.SampleType))
60
+	for i, t := range p.SampleType {
61
+		types[i] = t.Type
62
+	}
63
+	return types
64
+}

+ 100
- 0
profile/index_test.go Näytä tiedosto

@@ -0,0 +1,100 @@
1
+package profile
2
+
3
+import (
4
+	"testing"
5
+)
6
+
7
+func TestSampleIndexByName(t *testing.T) {
8
+	for _, c := range []struct {
9
+		desc              string
10
+		sampleTypes       []string
11
+		defaultSampleType string
12
+		index             string
13
+		want              int
14
+		wantError         bool
15
+	}{
16
+		{
17
+			desc:        "use last by default",
18
+			index:       "",
19
+			want:        1,
20
+			sampleTypes: []string{"zero", "default"},
21
+		},
22
+		{
23
+			desc:              "honour specified default",
24
+			index:             "",
25
+			want:              1,
26
+			defaultSampleType: "default",
27
+			sampleTypes:       []string{"zero", "default", "two"},
28
+		},
29
+		{
30
+			desc:              "invalid default is ignored",
31
+			index:             "",
32
+			want:              2,
33
+			defaultSampleType: "non-existent",
34
+			sampleTypes:       []string{"zero", "one", "default"},
35
+		},
36
+		{
37
+			desc:        "index by int",
38
+			index:       "0",
39
+			want:        0,
40
+			sampleTypes: []string{"zero", "one", "two"},
41
+		},
42
+		{
43
+			desc:              "index by int ignores default",
44
+			index:             "0",
45
+			want:              0,
46
+			defaultSampleType: "default",
47
+			sampleTypes:       []string{"zero", "default", "two"},
48
+		},
49
+		{
50
+			desc:        "index by name",
51
+			index:       "two",
52
+			want:        2,
53
+			sampleTypes: []string{"zero", "one", "two", "three"},
54
+		},
55
+		{
56
+			desc:              "index by name ignores default",
57
+			index:             "zero",
58
+			want:              0,
59
+			defaultSampleType: "default",
60
+			sampleTypes:       []string{"zero", "default", "two"},
61
+		},
62
+		{
63
+			desc:        "out of bound int causes error",
64
+			index:       "100",
65
+			wantError:   true,
66
+			sampleTypes: []string{"zero", "default"},
67
+		},
68
+		{
69
+			desc:        "unknown name causes error",
70
+			index:       "does not exist",
71
+			wantError:   true,
72
+			sampleTypes: []string{"zero", "default"},
73
+		},
74
+		{
75
+			desc:        "'inused_{x}' recognized for legacy '{x}'",
76
+			index:       "inuse_zero",
77
+			want:        0,
78
+			sampleTypes: []string{"zero", "default"},
79
+		},
80
+	} {
81
+		p := &Profile{
82
+			DefaultSampleType: c.defaultSampleType,
83
+			SampleType:        []*ValueType{},
84
+		}
85
+		for _, st := range c.sampleTypes {
86
+			p.SampleType = append(p.SampleType, &ValueType{Type: st, Unit: "milliseconds"})
87
+		}
88
+
89
+		got, err := p.SampleIndexByName(c.index)
90
+
91
+		switch {
92
+		case c.wantError && err == nil:
93
+			t.Errorf("%s: error should have been returned not index=%d, err=%v", c.desc, got, err)
94
+		case !c.wantError && err != nil:
95
+			t.Errorf("%s: unexpected got index=%d, err=%v; wanted index=%d, err=nil", c.desc, got, err, c.want)
96
+		case !c.wantError && got != c.want:
97
+			t.Errorf("%s: got index=%d, want index=%d", c.desc, got, c.want)
98
+		}
99
+	}
100
+}