func TestGroupMetricsBySpec_returns_single_metric_with_one_metric_in_metric_family(t *testing.T) {
	groupLabel := "node"
	metricName := "metricName"
	rawMetricName := "rawMetricName"
	entityName := "entityName"
	spec := definition.SpecGroups{
		groupLabel: definition.SpecGroup{
			Specs: []definition.Spec{
				{
					Name:      metricName,
					ValueFunc: FromValue(rawMetricName),
					Type:      metric.GAUGE,
				},
			},
		},
	}
	metricFamily := []MetricFamily{
		{
			Name: rawMetricName,
			Metrics: []Metric{
				{
					Value: GaugeValue(1),
					Labels: map[string]string{
						groupLabel: entityName,
					},
				},
			},
		},
	}
	expectedRawGroups := definition.RawGroups{
		groupLabel: {
			entityName: definition.RawMetrics{
				rawMetricName: Metric{
					Value: GaugeValue(1),
					Labels: map[string]string{
						groupLabel: entityName,
					},
				},
			},
		},
	}
	metricGroup, errs := GroupMetricsBySpec(spec, metricFamily)
	assert.Empty(t, errs)
	assert.Equal(t, expectedRawGroups, metricGroup)
}
To preserve old behavior.
package prometheus
import (
	"errors"
	"fmt"
	"math"
	"testing"
	"github.com/newrelic/infra-integrations-sdk/data/metric"
	model "github.com/prometheus/client_model/go"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/newrelic/nri-kubernetes/v2/src/definition"
)
var mFamily = []MetricFamily{
	{
		Name: "kube_pod_start_time",
		Metrics: []Metric{
			{
				Value: GaugeValue(1507117436),
				Labels: map[string]string{
					"namespace": "kube-system",
					"pod":       "fluentd-elasticsearch-jnqb7",
				},
			},
			{
				Value: GaugeValue(1510579152),
				Labels: map[string]string{
					"namespace": "kube-system",
					"pod":       "newrelic-infra-monitoring-cglrn",
				},
			},
		},
	},
	{
		Name: "kube_pod_info",
		Metrics: []Metric{
			{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"created_by_kind": "DaemonSet",
					"created_by_name": "fluentd-elasticsearch",
					"namespace":       "kube-system",
					"node":            "minikube",
					"pod":             "fluentd-elasticsearch-jnqb7",
				},
			},
			{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"created_by_kind": "DaemonSet",
					"created_by_name": "newrelic-infra-monitoring",
					"namespace":       "kube-system",
					"node":            "minikube",
					"pod":             "newrelic-infra-monitoring-cglrn",
				},
			},
		},
	},
	{
		Name: "kube_pod_labels",
		Metrics: []Metric{
			{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"label_app":                      "newrelic-infra-monitoring",
					"label_controller_revision_hash": "1758702902",
					"label_pod_template_generation":  "1",
					"namespace":                      "kube-system",
					"pod":                            "newrelic-infra-monitoring-cglrn",
				},
			},
			{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"label_name":                     "fluentd-elasticsearch",
					"label_controller_revision_hash": "3534845553",
					"label_pod_template_generation":  "1",
					"namespace":                      "kube-system",
					"pod":                            "fluentd-elasticsearch-jnqb7",
				},
			},
		},
	},
}
var spec = []definition.Spec{
	{
		Name:      "podStartTime",
		ValueFunc: FromValue("kube_pod_start_time"),
		Type:      metric.GAUGE,
	},
	{
		Name:      "podInfo.namespace",
		ValueFunc: FromLabelValue("kube_pod_info", "namespace"),
		Type:      metric.ATTRIBUTE,
	},
	{
		Name:      "podInfo.pod",
		ValueFunc: FromLabelValue("kube_pod_info", "pod"),
		Type:      metric.ATTRIBUTE,
	},
}
var containersSpec = definition.SpecGroups{
	"container": definition.SpecGroup{
		Specs: []definition.Spec{
			{
				Name:      "container",
				ValueFunc: FromLabelValue("kube_pod_container_info", "container"),
				Type:      metric.ATTRIBUTE,
			},
			{
				Name:      "image",
				ValueFunc: FromLabelValue("kube_pod_container_info", "image"),
				Type:      metric.ATTRIBUTE,
			},
			{
				Name:      "namespace",
				ValueFunc: FromLabelValue("kube_pod_container_info", "namespace"),
				Type:      metric.ATTRIBUTE,
			},
			{
				Name:      "pod",
				ValueFunc: FromLabelValue("kube_pod_container_info", "pod"),
				Type:      metric.ATTRIBUTE,
			},
		},
	},
}
var specs = definition.SpecGroups{
	"pod": definition.SpecGroup{
		Specs: spec,
	},
}
var metricFamilyContainersWithTheSameName = []MetricFamily{
	{
		Name: "kube_pod_container_info",
		Metrics: []Metric{
			{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"container": "kube-state-metrics",
					"image":     "gcr.io/google_containers/kube-state-metrics:v1.1.0",
					"namespace": "kube-system",
					"pod":       "newrelic-infra-monitoring-3bxnh",
				},
			},
			{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"container": "kube-state-metrics",
					"image":     "gcr.io/google_containers/kube-state-metrics:v1.1.0",
					"namespace": "kube-system",
					"pod":       "fluentd-elasticsearch-jnqb7",
				},
			},
		},
	},
}
var rawGroups = definition.RawGroups{
	"pod": {
		"fluentd-elasticsearch-jnqb7": definition.RawMetrics{
			"kube_pod_start_time": Metric{
				Value: GaugeValue(1507117436),
				Labels: map[string]string{
					"namespace": "kube-system",
					"pod":       "fluentd-elasticsearch-jnqb7",
				},
			},
			"kube_pod_info": Metric{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"created_by_kind": "ReplicaSet",
					"created_by_name": "fluentd-elasticsearch-fafnoa",
					"namespace":       "kube-system",
					"node":            "minikube",
					"pod":             "fluentd-elasticsearch-jnqb7",
				},
			},
			"kube_pod_status_phase": Metric{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"namespace": "kube-system",
					"pod":       "fluentd-elasticsearch-jnqb7",
					"phase":     "Pending",
				},
			},
			"kube_pod_status_scheduled": Metric{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"namespace": "kube-system",
					"pod":       "fluentd-elasticsearch-jnqb7",
					"condition": "false",
				},
			},
		},
		"newrelic-infra-monitoring-cglrn": definition.RawMetrics{
			"kube_pod_start_time": Metric{
				Value: GaugeValue(1510579152),
				Labels: map[string]string{
					"namespace": "kube-system",
					"pod":       "newrelic-infra-monitoring-cglrn",
				},
			},
			"kube_pod_info": Metric{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"created_by_kind": "DaemonSet",
					"created_by_name": "newrelic-infra-monitoring",
					"namespace":       "kube-system",
					"node":            "minikube",
					"pod":             "newrelic-infra-monitoring-cglrn",
				},
			},
		},
		"kubernetes-dashboard-77d8b98585-c8s22": definition.RawMetrics{
			"kube_pod_status_phase": Metric{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"namespace": "kube-system",
					"pod":       "kubernetes-dashboard-77d8b98585-c8s22",
					"phase":     "Pending",
				},
			},
			"kube_pod_status_scheduled": Metric{
				Value: GaugeValue(1),
				Labels: map[string]string{
					"namespace": "kube-system",
					"pod":       "kubernetes-dashboard-77d8b98585-c8s22",
					"condition": "true",
				},
			},
		},
	},
}
var rawGroupsIncompatibleType = definition.RawGroups{
	"pod": {
		"fluentd-elasticsearch-jnqb7": definition.RawMetrics{
			"kube_pod_start_time": "foo",
		},
	},
}
var summarySpec = definition.SpecGroups{
	"scheduler": definition.SpecGroup{
		Specs: []definition.Spec{
			{Name: "http_request_duration_microseconds", ValueFunc: FromSummary("http_request_duration_microseconds"), Type: metric.GAUGE},
		},
	},
}
func float64Ptr(f float64) *float64 {
	return &f
}
func uint64Ptr(u uint64) *uint64 {
	return &u
}
var summaryRawGroups = definition.RawGroups{
	"scheduler": {
		"kube-scheduler-minikube": {
			"http_request_duration_microseconds": []Metric{
				{
					Labels: Labels{"l2": "v2", "l1": "v1", "handler": "prometheus"},
					Value: &model.Summary{
						SampleCount: uint64Ptr(5),
						SampleSum:   float64Ptr(45),
						Quantile: []*model.Quantile{
							{
								Quantile:         float64Ptr(0.5),
								Value:            float64Ptr(42),
								XXX_unrecognized: nil,
							},
							{
								Quantile:         float64Ptr(0.9),
								Value:            float64Ptr(43),
								XXX_unrecognized: nil,
							},
							{
								Quantile:         float64Ptr(0.99),
								Value:            float64Ptr(44),
								XXX_unrecognized: nil,
							},
						},
						XXX_unrecognized: nil,
					},
				}, {
					Labels: Labels{"l2": "v2", "l1": "v1", "handler": "other"},
					Value: &model.Summary{
						SampleCount: uint64Ptr(5),
						SampleSum:   float64Ptr(45),
						Quantile: []*model.Quantile{
							{
								Quantile:         float64Ptr(0.5),
								Value:            float64Ptr(42),
								XXX_unrecognized: nil,
							},
							{
								Quantile:         float64Ptr(0.9),
								Value:            float64Ptr(43),
								XXX_unrecognized: nil,
							},
							{
								Quantile:         float64Ptr(0.99),
								Value:            float64Ptr(44),
								XXX_unrecognized: nil,
							},
						},
						XXX_unrecognized: nil,
					},
				},
			},
		},
	},
}
var summaryMetricFamily = []MetricFamily{
	{
		Name: "http_request_duration_microseconds",
		Type: "SUMMARY",
		Metrics: []Metric{
			{
				Labels: Labels{"l2": "v2", "l1": "v1", "handler": "prometheus"},
				Value: &model.Summary{
					SampleCount: uint64Ptr(5),
					SampleSum:   float64Ptr(45),
					Quantile: []*model.Quantile{
						{
							Quantile:         float64Ptr(0.5),
							Value:            float64Ptr(42),
							XXX_unrecognized: nil,
						},
						{
							Quantile:         float64Ptr(0.9),
							Value:            float64Ptr(43),
							XXX_unrecognized: nil,
						},
						{
							Quantile:         float64Ptr(0.99),
							Value:            float64Ptr(44),
							XXX_unrecognized: nil,
						},
					},
					XXX_unrecognized: nil,
				},
			},
			{
				Labels: Labels{"l2": "v2", "l1": "v1", "handler": "other"},
				Value: &model.Summary{
					SampleCount: uint64Ptr(5),
					SampleSum:   float64Ptr(45),
					Quantile: []*model.Quantile{
						{
							Quantile:         float64Ptr(0.5),
							Value:            float64Ptr(42),
							XXX_unrecognized: nil,
						},
						{
							Quantile:         float64Ptr(0.9),
							Value:            float64Ptr(43),
							XXX_unrecognized: nil,
						},
						{
							Quantile:         float64Ptr(0.99),
							Value:            float64Ptr(44),
							XXX_unrecognized: nil,
						},
					},
					XXX_unrecognized: nil,
				},
			},
		},
	},
}
func TestGroupMetricsBySpec_CorrectValue(t *testing.T) {
	expectedMetricGroup := definition.RawGroups{
		"pod": {
			"kube-system_fluentd-elasticsearch-jnqb7": definition.RawMetrics{
				"kube_pod_start_time": Metric{
					Value: GaugeValue(1507117436),
					Labels: map[string]string{
						"namespace": "kube-system",
						"pod":       "fluentd-elasticsearch-jnqb7",
					},
				},
				"kube_pod_info": Metric{
					Value: GaugeValue(1),
					Labels: map[string]string{
						"created_by_kind": "DaemonSet",
						"created_by_name": "fluentd-elasticsearch",
						"namespace":       "kube-system",
						"node":            "minikube",
						"pod":             "fluentd-elasticsearch-jnqb7",
					},
				},
				"kube_pod_labels": Metric{
					Value: GaugeValue(1),
					Labels: map[string]string{
						"label_name":                     "fluentd-elasticsearch",
						"label_controller_revision_hash": "3534845553",
						"label_pod_template_generation":  "1",
						"namespace":                      "kube-system",
						"pod":                            "fluentd-elasticsearch-jnqb7",
					},
				},
			},
			"kube-system_newrelic-infra-monitoring-cglrn": definition.RawMetrics{
				"kube_pod_start_time": Metric{
					Value: GaugeValue(1510579152),
					Labels: map[string]string{
						"namespace": "kube-system",
						"pod":       "newrelic-infra-monitoring-cglrn",
					},
				},
				"kube_pod_info": Metric{
					Value: GaugeValue(1),
					Labels: map[string]string{
						"created_by_kind": "DaemonSet",
						"created_by_name": "newrelic-infra-monitoring",
						"namespace":       "kube-system",
						"node":            "minikube",
						"pod":             "newrelic-infra-monitoring-cglrn",
					},
				},
				"kube_pod_labels": Metric{
					Value: GaugeValue(1),
					Labels: map[string]string{
						"label_app":                      "newrelic-infra-monitoring",
						"label_controller_revision_hash": "1758702902",
						"label_pod_template_generation":  "1",
						"namespace":                      "kube-system",
						"pod":                            "newrelic-infra-monitoring-cglrn",
					},
				},
			},
		},
	}
	metricGroup, errs := GroupMetricsBySpec(specs, mFamily)
	assert.Empty(t, errs)
	assert.Equal(t, expectedMetricGroup, metricGroup)
}
func TestGroupMetricsBySpec_CorrectValue_ContainersWithTheSameName(t *testing.T) {
	expectedMetricGroup := definition.RawGroups{
		"container": {
			"kube-system_fluentd-elasticsearch-jnqb7_kube-state-metrics": definition.RawMetrics{
				"kube_pod_container_info": Metric{
					Value: GaugeValue(1),
					Labels: map[string]string{
						"container": "kube-state-metrics",
						"image":     "gcr.io/google_containers/kube-state-metrics:v1.1.0",
						"namespace": "kube-system",
						"pod":       "fluentd-elasticsearch-jnqb7",
					},
				},
			},
			"kube-system_newrelic-infra-monitoring-3bxnh_kube-state-metrics": definition.RawMetrics{
				"kube_pod_container_info": Metric{
					Value: GaugeValue(1),
					Labels: map[string]string{
						"container": "kube-state-metrics",
						"image":     "gcr.io/google_containers/kube-state-metrics:v1.1.0",
						"namespace": "kube-system",
						"pod":       "newrelic-infra-monitoring-3bxnh",
					},
				},
			},
		},
	}
	metricGroup, errs := GroupMetricsBySpec(containersSpec, metricFamilyContainersWithTheSameName)
	assert.Empty(t, errs)
	assert.Equal(t, expectedMetricGroup, metricGroup)
}
func Test_GroupMetricsBySpec_does_not_add_unrelated_entity_metrics(t *testing.T) {
	groupLabelMetricName := "groupLabelMetricName"
	groupLabelRawMetricName := "groupLabelRawMetricName"
	groupLabelEntityName := "groupLabelEntityName"
	unrelatedMetricName := "unrelatedMetricName"
	unrelatedRawMetricName := "unrelatedRawMetricName"
	unreleatedEntityName := "unreleatedEntityName"
	cases := map[string]struct {
		groupLabel          string
		unrelatedLabel      string
		unrelatedMetricName string
	}{
		"from_daemonset_to_namespace": {
			groupLabel:          "namespace",
			unrelatedLabel:      "daemonset",
			unrelatedMetricName: fmt.Sprintf("%s_%s", groupLabelEntityName, unreleatedEntityName),
		},
		"from_pod_to_namespace": {
			groupLabel:          "namespace",
			unrelatedLabel:      "pod",
			unrelatedMetricName: fmt.Sprintf("%s_%s", groupLabelEntityName, unreleatedEntityName),
		},
		"from_endpoint_to_namespace": {
			groupLabel:          "namespace",
			unrelatedLabel:      "endpoint",
			unrelatedMetricName: fmt.Sprintf("%s_%s", groupLabelEntityName, unreleatedEntityName),
		},
		"from_service_to_namespace": {
			groupLabel:          "namespace",
			unrelatedLabel:      "service",
			unrelatedMetricName: fmt.Sprintf("%s_%s", groupLabelEntityName, unreleatedEntityName),
		},
		"from_deployment_to_namespace": {
			groupLabel:          "namespace",
			unrelatedLabel:      "deployment",
			unrelatedMetricName: fmt.Sprintf("%s_%s", groupLabelEntityName, unreleatedEntityName),
		},
		"from_replicaset_to_namespace": {
			groupLabel:          "namespace",
			unrelatedLabel:      "replicaset",
			unrelatedMetricName: fmt.Sprintf("%s_%s", groupLabelEntityName, unreleatedEntityName),
		},
		"from_pod_to_node": {
			groupLabel:          "node",
			unrelatedLabel:      "pod",
			unrelatedMetricName: fmt.Sprintf("_%s", unreleatedEntityName),
		},
	}
	for caseName, c := range cases {
		c := c
		t.Run(caseName, func(t *testing.T) {
			spec := definition.SpecGroups{
				c.groupLabel: definition.SpecGroup{
					Specs: []definition.Spec{
						{
							Name:      groupLabelMetricName,
							ValueFunc: FromValue(groupLabelRawMetricName),
							Type:      metric.GAUGE,
						},
					},
				},
				c.unrelatedLabel: definition.SpecGroup{
					Specs: []definition.Spec{
						{
							Name:      unrelatedMetricName,
							ValueFunc: FromValue(unrelatedRawMetricName),
							Type:      metric.GAUGE,
						},
					},
				},
			}
			metricFamily := []MetricFamily{
				{
					Name: groupLabelRawMetricName,
					Metrics: []Metric{
						{
							Value: GaugeValue(1),
							Labels: map[string]string{
								c.groupLabel: groupLabelEntityName,
							},
						},
					},
				},
				{
					Name: unrelatedRawMetricName,
					Metrics: []Metric{
						{
							Value: GaugeValue(1),
							Labels: map[string]string{
								c.groupLabel:     groupLabelEntityName,
								c.unrelatedLabel: unreleatedEntityName,
							},
						},
					},
				},
			}
			expectedRawGroups := definition.RawGroups{
				c.groupLabel: {
					groupLabelEntityName: definition.RawMetrics{
						groupLabelRawMetricName: Metric{
							Value: GaugeValue(1),
							Labels: map[string]string{
								c.groupLabel: groupLabelEntityName,
							},
						},
					},
				},
				c.unrelatedLabel: {
					c.unrelatedMetricName: definition.RawMetrics{
						unrelatedRawMetricName: Metric{
							Value: GaugeValue(1),
							Labels: map[string]string{
								c.groupLabel:     groupLabelEntityName,
								c.unrelatedLabel: unreleatedEntityName,
							},
						},
					},
				},
			}
			metricGroup, errs := GroupMetricsBySpec(spec, metricFamily)
			assert.Empty(t, errs)
			assert.Equal(t, expectedRawGroups, metricGroup)
		})
	}
}
func TestGroupMetricsBySpec_EmptyMetricFamily(t *testing.T) {
	var emptyMetricFamily []MetricFamily
	metricGroup, errs := GroupMetricsBySpec(specs, emptyMetricFamily)
	assert.Len(t, errs, 1)
	assert.Equal(t, errors.New("no data found for pod object"), errs[0])
	assert.Empty(t, metricGroup)
}