github.com/grafana/pyroscope@v1.18.0/pkg/test/integration/ingest_speedscope_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"testing"
     5  
     6  	"connectrpc.com/connect"
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/require"
     9  
    10  	profilev1 "github.com/grafana/pyroscope/api/gen/proto/go/google/v1"
    11  )
    12  
    13  type speedscopeTestDataStruct struct {
    14  	name            string
    15  	speedscopeFile  string
    16  	expectStatus    int
    17  	expectedMetrics []expectedMetric
    18  }
    19  
    20  const (
    21  	testdataDirSpeedscope = repoRoot + "pkg/og/convert/speedscope/testdata"
    22  )
    23  
    24  var (
    25  	speedscopeTestData = []speedscopeTestDataStruct{
    26  		{
    27  			name:           "single profile evented",
    28  			speedscopeFile: testdataDirSpeedscope + "/simple.speedscope.json",
    29  			expectStatus:   200,
    30  			expectedMetrics: []expectedMetric{
    31  				// The difference between the metric name here and in the other test is a quirk in
    32  				// how the speedscope parsing logic. Only multi profile uploads will
    33  				// append the unit to the metric name which is parsed differently downstream.
    34  				{"process_cpu:cpu:nanoseconds:cpu:nanoseconds", nil, 0},
    35  			},
    36  		},
    37  		{
    38  			name:           "multi profile sampled",
    39  			speedscopeFile: testdataDirSpeedscope + "/two-sampled.speedscope.json",
    40  			expectStatus:   200,
    41  			expectedMetrics: []expectedMetric{
    42  				{"wall:wall:nanoseconds:cpu:nanoseconds", nil, 0},
    43  			},
    44  		},
    45  		{
    46  			name:           "multi profile samples bytes units",
    47  			speedscopeFile: testdataDirSpeedscope + "/two-sampled-bytes.speedscope.json",
    48  			expectStatus:   200,
    49  			expectedMetrics: []expectedMetric{
    50  				{"memory:samples:bytes::", nil, 0},
    51  			},
    52  		},
    53  	}
    54  )
    55  
    56  func TestIngestSpeedscope(t *testing.T) {
    57  	EachPyroscopeTest(t, func(p *PyroscopeTest, t *testing.T) {
    58  		for _, td := range speedscopeTestData {
    59  			t.Run(td.name, func(t *testing.T) {
    60  				rb := p.NewRequestBuilder(t)
    61  				req := rb.IngestSpeedscopeRequest(td.speedscopeFile)
    62  				p.Ingest(t, req, td.expectStatus)
    63  
    64  				if td.expectStatus == 200 {
    65  					for _, metric := range td.expectedMetrics {
    66  						rb.Render(metric.name)
    67  						profile := rb.SelectMergeProfile(metric.name, metric.query)
    68  						assertSpeedscopeProfile(t, profile)
    69  					}
    70  				}
    71  			})
    72  		}
    73  	})
    74  }
    75  
    76  func assertSpeedscopeProfile(t *testing.T, resp *connect.Response[profilev1.Profile]) {
    77  	assert.Equal(t, 1, len(resp.Msg.SampleType), "SampleType should be set")
    78  	require.Greater(t, len(resp.Msg.Sample), 0, "Profile should contain samples")
    79  	assert.Greater(t, resp.Msg.Sample[0].Value[0], int64(0), "Sample value should be positive")
    80  }