<commit_before>// Copyright 2018, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package stackdriver

import (
	"context"
	"fmt"
	"strings"
	"testing"

	resourcepb "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1"
	"github.com/golang/protobuf/ptypes/timestamp"
	"google.golang.org/api/option"
	distributionpb "google.golang.org/genproto/googleapis/api/distribution"
	labelpb "google.golang.org/genproto/googleapis/api/label"
	googlemetricpb "google.golang.org/genproto/googleapis/api/metric"
	monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres"
	monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
	"google.golang.org/grpc"

	metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
	"github.com/golang/protobuf/ptypes/wrappers"
	"github.com/google/go-cmp/cmp"
	"go.opencensus.io/resource/resourcekeys"
)

func TestExportTimeSeriesWithDifferentLabels(t *testing.T) {
	server, addr, doneFn := createFakeServer(t)
	defer doneFn()

	// Now create a gRPC connection to the agent.
	conn, err := grpc.Dial(addr, grpc.WithInsecure())
	if err != nil {
		t.Fatalf("Failed to make a gRPC connection to the agent: %v", err)
	}
	defer conn.Close()

	// Finally create the OpenCensus stats exporter
	exporterOptions := Options{
		ProjectID:               "equivalence",
		MonitoringClientOptions: []option.ClientOption{option.WithGRPCConn(conn)},

		// Set empty labels to avoid the opencensus-task
		DefaultMonitoringLabels: &Labels{},
		MapResource:             defaultMapResource,
	}
	se, err := newStatsExporter(exporterOptions)
	if err != nil {
		t.Fatalf("Failed to create the statsExporter: %v", err)
	}

	startTimestamp := &timestamp.Timestamp{
		Seconds: 1543160298,
		Nanos:   100000090,
	}
	endTimestamp := &timestamp.Timestamp{
		Seconds: 1543160298,
		Nanos:   100000997,
	}

	// Generate the proto Metrics.
	var metricPbs []*metricspb.Metric
	metricPbs = append(metricPbs,
		&metricspb.Metric{
			MetricDescriptor: &metricspb.MetricDescriptor{
				Name:        "ocagent.io/calls",
				Description: "The number of the various calls",
				LabelKeys: []*metricspb.LabelKey{
					{
						Key: "empty_key",
					},
					{
						Key: "operation_type",
					},
				},
				Unit: "1",
				Type: metricspb.MetricDescriptor_CUMULATIVE_INT64,
			},
			Timeseries: []*metricspb.TimeSeries{
				{
					StartTimestamp: startTimestamp,
					LabelValues: []*metricspb.LabelValue{
						{
							Value:    "",
							HasValue: true,
						},
						{
							Value:    "test_1",
							HasValue: true,
						},
					},
					Points: []*metricspb.Point{
						{
							Timestamp: endTimestamp,
							Value:     &metricspb.Point_Int64Value{Int64Value: int64(1)},
						},
					},
				},
				{
					StartTimestamp: startTimestamp,
					LabelValues: []*metricspb.LabelValue{
						{
							Value:    "",
							HasValue: true,
						},
						{
							Value:    "test_2",
							HasValue: true,
						},
					},
					Points: []*metricspb.Point{
						{
							Timestamp: endTimestamp,
							Value:     &metricspb.Point_Int64Value{Int64Value: int64(1)},
						},
					},
				},
			},
		})

	var wantTimeSeries []*monitoringpb.CreateTimeSeriesRequest
	wantTimeSeries = append(wantTimeSeries, &monitoringpb.CreateTimeSeriesRequest{
		Name: "projects/equivalence",
		TimeSeries: []*monitoringpb.TimeSeries{
			{
				Metric: &googlemetricpb.Metric{
					Type: "custom.googleapis.com/opencensus/ocagent.io/calls",
					Labels: map[string]string{
						"empty_key":      "",
						"operation_type": "test_1",
					},
				},
				Resource: &monitoredrespb.MonitoredResource{
					Type: "global",
				},
				MetricKind: googlemetricpb.MetricDescriptor_CUMULATIVE,
				ValueType:  googlemetricpb.MetricDescriptor_INT64,
				Points: []*monitoringpb.Point{
					{
						Interval: &monitoringpb.TimeInterval{
							StartTime: startTimestamp,
							EndTime:   endTimestamp,
						},
						Value: &monitoringpb.TypedValue{
							Value: &monitoringpb.TypedValue_Int64Value{
								Int64Value: 1,
							},
						},
					},
				},
			},
			{
				Metric: &googlemetricpb.Metric{
					Type: "custom.googleapis.com/opencensus/ocagent.io/calls",
					Labels: map[string]string{
						"empty_key":      "",
						"operation_type": "test_2",
					},
				},
				Resource: &monitoredrespb.MonitoredResource{
					Type: "global",
				},
				MetricKind: googlemetricpb.MetricDescriptor_CUMULATIVE,
				ValueType:  googlemetricpb.MetricDescriptor_INT64,
				Points: []*monitoringpb.Point{
					{
						Interval: &monitoringpb.TimeInterval{
							StartTime: startTimestamp,
							EndTime:   endTimestamp,
						},
						Value: &monitoringpb.TypedValue{
							Value: &monitoringpb.TypedValue_Int64Value{
								Int64Value: 1,
							},
						},
					},
				},
			},
		}, //<metric:<type:"custom.googleapis.com/opencensus/ocagent.io/calls" labels:<key:"opencensus_task" value:"<EMAIL>" > > resource:<type:"global" > metric_kind:CUMULATIVE value_type:INT64 points:<interval:<end_time:<seconds:1001 > start_time:<seconds:1000 > > value:<int64_value:8 > > > time_series:<metric:<type:"custom.googleapis.com/opencensus/ocagent.io/calls" labels:<key:"opencensus_<EMAIL>" value:"<EMAIL>" > > resource:<type:"global" > metric_kind:CUMULATIVE value_type:INT64 points:<interval:<end_time:<seconds:1001 > start_time:<seconds:1000 > > value:<int64_value:8 > > > `,
	})

	// Export the proto Metrics to the Stackdriver backend.
	se.PushMetricsProto(context.Background(), nil, nil, metricPbs)
	se.Flush()

	var gotTimeSeries []*monitoringpb.CreateTimeSeriesRequest
	server.forEachStackdriverTimeSeries(func(sdt *monitoringpb.CreateTimeSeriesRequest) {
		gotTimeSeries = append(gotTimeSeries, sdt)
	})

	requireTimeSeriesRequestEqual(t, gotTimeSeries, wantTimeSeries)
}

func TestProtoMetricToCreateTimeSeriesRequest(t *testing.T) {
	startTimestamp := &timestamp.Timestamp{
		Seconds: 1543160298,
		Nanos:   100000090,
	}
	endTimestamp := &timestamp.Timestamp{
		Seconds: 1543160298,
		Nanos:   100000997,
	}

	tests := []struct {
		name          string
		in            *metricspb.Metric
		want          []*monitoringpb.CreateTimeSeriesRequest
		wantErr       string
		statsExporter *statsExporter<commit_msg>Remove unnecessary comment, check errors for PushMetricsProto (#204)<commit_after>// Copyright 2018, OpenCensus Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package stackdriver

import (
	"context"
	"fmt"
	"strings"
	"testing"

	resourcepb "github.com/census-instrumentation/opencensus-proto/gen-go/resource/v1"
	"github.com/golang/protobuf/ptypes/timestamp"
	"google.golang.org/api/option"
	distributionpb "google.golang.org/genproto/googleapis/api/distribution"
	labelpb "google.golang.org/genproto/googleapis/api/label"
	googlemetricpb "google.golang.org/genproto/googleapis/api/metric"
	monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres"
	monitoringpb "google.golang.org/genproto/googleapis/monitoring/v3"
	"google.golang.org/grpc"

	metricspb "github.com/census-instrumentation/opencensus-proto/gen-go/metrics/v1"
	"github.com/golang/protobuf/ptypes/wrappers"
	"github.com/google/go-cmp/cmp"
	"go.opencensus.io/resource/resourcekeys"
)

func TestExportTimeSeriesWithDifferentLabels(t *testing.T) {
	server, addr, doneFn := createFakeServer(t)
	defer doneFn()

	// Now create a gRPC connection to the agent.
	conn, err := grpc.Dial(addr, grpc.WithInsecure())
	if err != nil {
		t.Fatalf("Failed to make a gRPC connection to the agent: %v", err)
	}
	defer conn.Close()

	// Finally create the OpenCensus stats exporter
	exporterOptions := Options{
		ProjectID:               "equivalence",
		MonitoringClientOptions: []option.ClientOption{option.WithGRPCConn(conn)},

		// Set empty labels to avoid the opencensus-task
		DefaultMonitoringLabels: &Labels{},
		MapResource:             defaultMapResource,
	}
	se, err := newStatsExporter(exporterOptions)
	if err != nil {
		t.Fatalf("Failed to create the statsExporter: %v", err)
	}

	startTimestamp := &timestamp.Timestamp{
		Seconds: 1543160298,
		Nanos:   100000090,
	}
	endTimestamp := &timestamp.Timestamp{
		Seconds: 1543160298,
		Nanos:   100000997,
	}

	// Generate the proto Metrics.
	var metricPbs []*metricspb.Metric
	metricPbs = append(metricPbs,
		&metricspb.Metric{
			MetricDescriptor: &metricspb.MetricDescriptor{
				Name:        "ocagent.io/calls",
				Description: "The number of the various calls",
				LabelKeys: []*metricspb.LabelKey{
					{
						Key: "empty_key",
					},
					{
						Key: "operation_type",
					},
				},
				Unit: "1",
				Type: metricspb.MetricDescriptor_CUMULATIVE_INT64,
			},
			Timeseries: []*metricspb.TimeSeries{
				{
					StartTimestamp: startTimestamp,
					LabelValues: []*metricspb.LabelValue{
						{
							Value:    "",
							HasValue: true,
						},
						{
							Value:    "test_1",
							HasValue: true,
						},
					},
					Points: []*metricspb.Point{
						{
							Timestamp: endTimestamp,
							Value:     &metricspb.Point_Int64Value{Int64Value: int64(1)},
						},
					},
				},
				{
					StartTimestamp: startTimestamp,
					LabelValues: []*metricspb.LabelValue{
						{
							Value:    "",
							HasValue: true,
						},
						{
							Value:    "test_2",
							HasValue: true,
						},
					},
					Points: []*metricspb.Point{
						{
							Timestamp: endTimestamp,
							Value:     &metricspb.Point_Int64Value{Int64Value: int64(1)},
						},
					},
				},
			},
		})

	var wantTimeSeries []*monitoringpb.CreateTimeSeriesRequest
	wantTimeSeries = append(wantTimeSeries, &monitoringpb.CreateTimeSeriesRequest{
		Name: "projects/equivalence",
		TimeSeries: []*monitoringpb.TimeSeries{
			{
				Metric: &googlemetricpb.Metric{
					Type: "custom.googleapis.com/opencensus/ocagent.io/calls",
					Labels: map[string]string{
						"empty_key":      "",
						"operation_type": "test_1",
					},
				},
				Resource: &monitoredrespb.MonitoredResource{
					Type: "global",
				},
				MetricKind: googlemetricpb.MetricDescriptor_CUMULATIVE,
				ValueType:  googlemetricpb.MetricDescriptor_INT64,
				Points: []*monitoringpb.Point{
					{
						Interval: &monitoringpb.TimeInterval{
							StartTime: startTimestamp,
							EndTime:   endTimestamp,
						},
						Value: &monitoringpb.TypedValue{
							Value: &monitoringpb.TypedValue_Int64Value{
								Int64Value: 1,
							},
						},
					},
				},
			},
			{
				Metric: &googlemetricpb.Metric{
					Type: "custom.googleapis.com/opencensus/ocagent.io/calls",
					Labels: map[string]string{
						"empty_key":      "",
						"operation_type": "test_2",
					},
				},
				Resource: &monitoredrespb.MonitoredResource{
					Type: "global",
				},
				MetricKind: googlemetricpb.MetricDescriptor_CUMULATIVE,
				ValueType:  googlemetricpb.MetricDescriptor_INT64,
				Points: []*monitoringpb.Point{
					{
						Interval: &monitoringpb.TimeInterval{
							StartTime: startTimestamp,
							EndTime:   endTimestamp,
						},
						Value: &monitoringpb.TypedValue{
							Value: &monitoringpb.TypedValue_Int64Value{
								Int64Value: 1,
							},
						},
					},
				},
			},
		},
	})

	// Export the proto Metrics to the Stackdriver backend.
	dropped, err := se.PushMetricsProto(context.Background(), nil, nil, metricPbs)
	if dropped != 0 || err != nil {
		t.Fatalf("Error pushing metrics, dropped:%d err:%v", dropped, err)
	}

	var gotTimeSeries []*monitoringpb.CreateTimeSeriesRequest
	server.forEachStackdriverTimeSeries(func(sdt *monitoringpb.CreateTimeSeriesRequest) {
		gotTimeSeries = append(gotTimeSeries, sdt)
	})

	requireTimeSeriesRequestEqual(t, gotTimeSeries, wantTimeSeries)
}

func TestProtoMetricToCreateTimeSeriesRequest(t *testing.T) {
	startTimestamp := &timestamp.Timestamp{
		Seconds: 1543160298,
		Nanos:   100000090,
	}
	endTimestamp := &timestamp.Timestamp{
		Seconds: 1543160298,
		Nanos:   100000997,
	}

	tests := []struct {
		name          string
		in            *metricspb.Metric
		want          []*monitoringpb.CreateTimeSeriesRequest
		wantErr       string
		statsExporter *statsExporter
{'fraction_non_alphanumeric': 0.12021065486185316, 'fraction_numerical': 0.020912837734696994, 'mean_word_length': 3.283425956194835, 'pattern_counts': {'":': 8, '<': 24, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5178024', 'n_tokens_mistral': 5413, 'n_tokens_neox': 4202, 'n_words': 811}