Files
traces/pkg/httpclient/client_test.go
David HamandGitHub b78a82e085 feat: Add option to run tempo-vulture in validation mode (#5605)
* feat: Read/write validation working, simple search

* feat: WIP on adding search for each trace

* feat: exposed port 4317

* feat: Extracted write, read, search into separate methods

* feat: Updated to use new service code

* feat: Added MockClock; fixed an error in a prev mock

* feat: Added tests for the three parts of the validation

* feat: Added runValidation test

* docs: Updated changelog

* docs: CHANGELOG.md without Prettier LOL

* fix: Updates for linter

* fix: more linter changes

* feat: Added new methods to create OTLP exporters with auth enabled

Also updated old functions to call the new, for backward compatibility

* feat: Added TempoBasicAuthToken to ValidationConfig

* feat: Updated to use new auth-enabled versions

* feat: Added EmitBatchesWithContext

* feat: Moved validationConfig setup to its own function

* chore: lowercase errors

* feat: Added context-aware methods

* feat: Added methods to mocks

* fix: return 1 rather than exit

* renamed sleep method

* fix: linter issue

* WIP on validateTraceSearch

* feat: Set ingester rf to 3; formatting

* feat: Test updates

* fix: linter issues

* fix: moar linter issues

* feat: Made TEMPO_ACCESS_POLICY_TOKEN a const

* feat: Also moved defer() statement

* feat: PR comment fixes

- Use debug level in that debug function
- return err instead of ctx.Err()
- Update vs.sleepWithContext to use the vs.clock so it's faster in tests

* feat: Add constants for headers

* feat: Refactor for withContext

Merged all of my new 'withContext' metjods with their originals, and updated all the callers to pass in context.Background() so it would compile

* feat: Update to use the new const

* docs: Changelog formatting

* feat: rename header
2025-10-08 14:50:55 +00:00

124 lines
3.5 KiB
Go

package httpclient
import (
"bytes"
"context"
"fmt"
"io"
"net/http"
"testing"
"github.com/gogo/protobuf/proto"
"github.com/grafana/tempo/pkg/tempopb"
"github.com/stretchr/testify/assert"
)
type MockRoundTripper func(r *http.Request) *http.Response
func (f MockRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
return f(r), nil
}
func TestQueryTrace(t *testing.T) {
trace := &tempopb.Trace{}
t.Run("returns a trace when is found", func(t *testing.T) {
mockTransport := MockRoundTripper(func(req *http.Request) *http.Response {
assert.Equal(t, "www.tempo.com/api/traces/100", req.URL.Path)
assert.Equal(t, "application/protobuf", req.Header.Get("Accept"))
response, _ := proto.Marshal(trace)
return &http.Response{
StatusCode: 200,
Body: io.NopCloser(bytes.NewReader(response)),
}
})
client := New("www.tempo.com", "1000")
client.WithTransport(mockTransport)
response, err := client.QueryTrace("100")
assert.NoError(t, err)
assert.True(t, proto.Equal(trace, response))
})
t.Run("includes the recentDataTarget header", func(t *testing.T) {
mockTransport := MockRoundTripper(func(req *http.Request) *http.Response {
assert.Equal(t, liveStoreHeaderValue, req.Header.Get(recentDataTargetHeader))
response, _ := proto.Marshal(trace)
return &http.Response{
StatusCode: 200,
Body: io.NopCloser(bytes.NewReader(response)),
}
})
client := New("www.tempo.com", "1000")
client.QueryLiveStores = true
client.WithTransport(mockTransport)
response, err := client.QueryTrace("100")
assert.NoError(t, err)
assert.True(t, proto.Equal(trace, response))
})
t.Run("returns a trace not found error on 404", func(t *testing.T) {
mockTransport := MockRoundTripper(func(_ *http.Request) *http.Response {
return &http.Response{
StatusCode: 404,
Body: nil,
}
})
client := New("www.tempo.com", "1000")
client.WithTransport(mockTransport)
response, err := client.QueryTrace("notfound")
assert.Error(t, err)
assert.Nil(t, response)
})
}
func TestQueryTraceWithRange(t *testing.T) {
trace := &tempopb.Trace{}
t.Run("returns an error if start time is greater than end time", func(t *testing.T) {
client := New("www.tempo.com", "1000")
response, err := client.QueryTraceWithRange(context.Background(), "notfound", 3000, 2000)
assert.Error(t, err)
assert.Nil(t, response)
})
t.Run("returns a trace with range when is found", func(t *testing.T) {
mockTransport := MockRoundTripper(func(req *http.Request) *http.Response {
assert.Equal(t, "www.tempo.com/api/traces/100?end=2000&start=1000", fmt.Sprint(req.URL))
assert.Equal(t, "application/protobuf", req.Header.Get("Accept"))
response, _ := proto.Marshal(trace)
return &http.Response{
StatusCode: 200,
Body: io.NopCloser(bytes.NewReader(response)),
}
})
client := New("www.tempo.com", "1000")
client.WithTransport(mockTransport)
response, err := client.QueryTraceWithRange(context.Background(), "100", 1000, 2000)
assert.NoError(t, err)
assert.True(t, proto.Equal(trace, response))
})
t.Run("returns a trace with range not found error on 404", func(t *testing.T) {
mockTransport := MockRoundTripper(func(_ *http.Request) *http.Response {
return &http.Response{
StatusCode: 404,
Body: nil,
}
})
client := New("www.tempo.com", "1000")
client.WithTransport(mockTransport)
response, err := client.QueryTraceWithRange(context.Background(), "notfound", 1000, 2000)
assert.Error(t, err)
assert.Nil(t, response)
})
}