Skip to content

Commit

Permalink
Dedicated integration test
Browse files Browse the repository at this point in the history
  • Loading branch information
codebien committed May 29, 2023
1 parent 5395b42 commit 1d7eed8
Show file tree
Hide file tree
Showing 2 changed files with 285 additions and 0 deletions.
155 changes: 155 additions & 0 deletions output/cloud/expv2/integration/integration_test.go
@@ -0,0 +1,155 @@
package integration

import (
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"testing"
"time"

"github.com/klauspost/compress/snappy"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.k6.io/k6/cloudapi"
"go.k6.io/k6/lib/testutils"
"go.k6.io/k6/lib/types"
"go.k6.io/k6/metrics"
"go.k6.io/k6/output/cloud/expv2"
"go.k6.io/k6/output/cloud/expv2/pbcloud"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"gopkg.in/guregu/null.v3"
)

// This test runs an integration tests for the Output cloud.
// It only calls public API of the Output and
// it implements a concrete http endpoint where to get
// the protobuf flush requests.

func TestOutputFlush(t *testing.T) {
// TODO: it has 3s for aggregation time
// then it means it will execute for +3s that it is a waste of time
// because it isn't really required.
// Reduce the aggregation time (to 1s?) then run always.
t.Skip("Skip the integration test, if required enable it manually")
t.Parallel()

results := make(chan *pbcloud.MetricSet)
ts := httptest.NewServer(metricsHandler(results))
defer ts.Close()

// init conifg
c := cloudapi.NewConfig()
c.Host = null.StringFrom(ts.URL)
c.Token = null.StringFrom("my-secret-token")
c.AggregationPeriod = types.NullDurationFrom(3 * time.Second)
c.AggregationWaitPeriod = types.NullDurationFrom(1 * time.Second)

// init and start the output
o, err := expv2.New(testutils.NewLogger(t), c)
require.NoError(t, err)
o.SetReferenceID("my-test-run-id-123")
require.NoError(t, o.Start())

// collect and flush samples
o.AddMetricSamples([]metrics.SampleContainer{
testSamples(),
})

// wait for results
mset := <-results
close(results)
assert.NoError(t, o.StopWithTestError(nil))

// read and convert the json version
// of the expected protobuf sent request
var exp pbcloud.MetricSet
expjs, err := os.ReadFile("./testdata/metricset.json") //nolint:forbidigo // ReadFile here is used in a test
require.NoError(t, err)
err = protojson.Unmarshal(expjs, &exp)
require.NoError(t, err)

msetjs, err := protojson.Marshal(mset)
require.NoError(t, err)
assert.JSONEq(t, string(expjs), string(msetjs))
}

func metricsHandler(results chan<- *pbcloud.MetricSet) http.HandlerFunc {
return func(rw http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
if token != "Token my-secret-token" {
http.Error(rw, fmt.Sprintf("token is required; got %q", token), http.StatusUnauthorized)
return
}
b, err := io.ReadAll(r.Body)
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
mset, err := metricSetFromRequest(b)
if err != nil {
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
results <- mset
}
}

func metricSetFromRequest(b []byte) (*pbcloud.MetricSet, error) {
b, err := snappy.Decode(nil, b)
if err != nil {
return nil, err
}
var mset pbcloud.MetricSet
err = proto.Unmarshal(b, &mset)
if err != nil {
return nil, err
}
return &mset, nil
}

func testSamples() metrics.Samples {
r := metrics.NewRegistry()
m1 := r.MustNewMetric("metric_counter_1", metrics.Counter)
m2 := r.MustNewMetric("metric_gauge_2", metrics.Gauge)
m3 := r.MustNewMetric("metric_rate_3", metrics.Rate)
m4 := r.MustNewMetric("metric_trend_4", metrics.Trend)

samples := []metrics.Sample{
{
TimeSeries: metrics.TimeSeries{
Metric: m1,
Tags: r.RootTagSet().With("my_label_1", "my_label_value_1"),
},
Time: time.Date(2023, time.May, 1, 1, 0, 0, 0, time.UTC),
Value: 42.2,
},
{
TimeSeries: metrics.TimeSeries{
Metric: m2,
Tags: r.RootTagSet().With("my_label_2", "my_label_value_2"),
},
Time: time.Date(2023, time.May, 1, 2, 0, 0, 0, time.UTC),
Value: 3.14,
},
{
TimeSeries: metrics.TimeSeries{
Metric: m3,
Tags: r.RootTagSet().With("my_label_3", "my_label_value_3"),
},
Time: time.Date(2023, time.May, 1, 3, 0, 0, 0, time.UTC),
Value: 2.718,
},
{
TimeSeries: metrics.TimeSeries{
Metric: m4,
Tags: r.RootTagSet().With("my_label_4", "my_label_value_4"),
},
Time: time.Date(2023, time.May, 1, 4, 0, 0, 0, time.UTC),
Value: 186,
},
}
return samples
}
130 changes: 130 additions & 0 deletions output/cloud/expv2/integration/testdata/metricset.json
@@ -0,0 +1,130 @@
{
"metrics": [
{
"name": "metric_counter_1",
"type": "METRIC_TYPE_COUNTER",
"timeSeries": [
{
"labels": [
{
"name": "__name__",
"value": "metric_counter_1"
},
{
"name": "test_run_id",
"value": "my-test-run-id-123"
},
{
"name": "my_label_1",
"value": "my_label_value_1"
}
],
"aggregationPeriod": 3,
"counterSamples": {
"values": [
{
"time": "2023-05-01T01:00:00Z",
"value": 42.2
}
]
}
}
]
},
{
"name": "metric_gauge_2",
"type": "METRIC_TYPE_GAUGE",
"timeSeries": [
{
"labels": [
{
"name": "__name__",
"value": "metric_gauge_2"
},
{
"name": "test_run_id",
"value": "my-test-run-id-123"
},
{
"name": "my_label_2",
"value": "my_label_value_2"
}
],
"aggregationPeriod": 3,
"gaugeSamples": {
"values": [
{
"time": "2023-05-01T02:00:00Z",
"last": 3.14,
"min": 3.14,
"max": 3.14
}
]
}
}
]
},
{
"name": "metric_rate_3",
"type": "METRIC_TYPE_RATE",
"timeSeries": [
{
"labels": [
{
"name": "__name__",
"value": "metric_rate_3"
},
{
"name": "test_run_id",
"value": "my-test-run-id-123"
},
{
"name": "my_label_3",
"value": "my_label_value_3"
}
],
"aggregationPeriod": 3,
"rateSamples": {
"values": [
{
"time": "2023-05-01T03:00:00Z",
"nonzeroCount": 1,
"totalCount": 1
}
]
}
}
]
},
{
"name": "metric_trend_4",
"type": "METRIC_TYPE_TREND",
"timeSeries": [
{
"labels": [
{
"name": "__name__",
"value": "metric_trend_4"
},
{
"name": "test_run_id",
"value": "my-test-run-id-123"
},
{
"name": "my_label_4",
"value": "my_label_value_4"
}
],
"aggregationPeriod": 3,
"trendHdrSamples": {
"values": [
{
"time": "2023-05-01T04:00:00Z"
}
]
}
}
]
}
]
}

0 comments on commit 1d7eed8

Please sign in to comment.