| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- package exporter
- import (
- "reflect"
- "testing"
- "time"
- "github.com/opencost/opencost/core/pkg/diagnostics"
- "github.com/opencost/opencost/core/pkg/heartbeat"
- "github.com/opencost/opencost/core/pkg/model"
- "github.com/opencost/opencost/core/pkg/model/pb"
- "github.com/opencost/opencost/core/pkg/opencost"
- "github.com/opencost/opencost/core/pkg/util"
- "github.com/opencost/opencost/core/pkg/util/json"
- "google.golang.org/protobuf/proto"
- )
- type decoderTestCase[T any] struct {
- name string
- data []byte
- want *T
- wantErr bool
- }
- func generateBadBytes() []byte {
- buff := util.NewBuffer()
- for i := 0; i < 10; i++ {
- buff.WriteUInt64(9999999)
- }
- return buff.Bytes()
- }
- func TestBingenDecoder(t *testing.T) {
- badBytes := generateBadBytes()
- now := time.Now().UTC().Truncate(24 * time.Hour)
- start := now.Add(-(24 * 5) * time.Hour)
- // Define and Run Allocation Tests
- allocSet := opencost.GenerateMockAllocationSet(start)
- allocSetRaw, err := allocSet.MarshalBinary()
- if err != nil {
- t.Errorf("failed to marshal allocation set: %s", err.Error())
- }
- allocTests := []decoderTestCase[opencost.AllocationSet]{
- {
- name: "allocation valid",
- data: allocSetRaw,
- want: allocSet,
- wantErr: false,
- },
- {
- name: "allocation invalid",
- data: badBytes,
- want: nil,
- wantErr: true,
- },
- }
- testDecoder(t, BingenDecoder, allocTests)
- // Define and Run Asset Tests
- assetSet := opencost.GenerateMockAssetSet(start, 24*time.Hour)
- assetSetRaw, err := assetSet.MarshalBinary()
- if err != nil {
- t.Errorf("failed to marshal asset set: %s", err.Error())
- }
- assetTests := []decoderTestCase[opencost.AssetSet]{
- {
- name: "asset valid",
- data: assetSetRaw,
- want: assetSet,
- wantErr: false,
- },
- {
- name: "asset invalid",
- data: badBytes,
- want: nil,
- wantErr: true,
- },
- }
- testDecoder(t, BingenDecoder, assetTests)
- // Define and Run Cloud Cost Tests
- CloudCostSet := opencost.GenerateMockCloudCostSet(start, start.Add(24*time.Hour), "gcp", "gke")
- CloudCostSetRaw, err := CloudCostSet.MarshalBinary()
- if err != nil {
- t.Errorf("failed to marshal cloud cost set: %s", err.Error())
- }
- cloudCostTests := []decoderTestCase[opencost.CloudCostSet]{
- {
- name: "cloud cost valid",
- data: CloudCostSetRaw,
- want: CloudCostSet,
- wantErr: false,
- },
- {
- name: "cloud cost invalid",
- data: badBytes,
- want: nil,
- wantErr: true,
- },
- }
- testDecoder(t, BingenDecoder, cloudCostTests)
- // Define and Run Network Insight Tests
- networkInsightSet := opencost.GenerateMockNetworkInsightSet(start, start.Add(24*time.Hour))
- networkInsightSetRaw, err := networkInsightSet.MarshalBinary()
- if err != nil {
- t.Errorf("failed to marshal network insight set: %s", err.Error())
- }
- networkInsightTests := []decoderTestCase[opencost.NetworkInsightSet]{
- {
- name: "network insight valid",
- data: networkInsightSetRaw,
- want: networkInsightSet,
- wantErr: false,
- },
- {
- name: "network insight invalid",
- data: badBytes,
- want: nil,
- wantErr: true,
- },
- }
- testDecoder(t, BingenDecoder, networkInsightTests)
- }
- func TestJsonDecoder(t *testing.T) {
- badBytes := generateBadBytes()
- now := time.Now().UTC().Truncate(24 * time.Hour)
- start := now.Add(-(24 * 5) * time.Hour)
- hb := heartbeat.Heartbeat{
- Id: "heartBeatID",
- Timestamp: start,
- Uptime: 123,
- Application: "mock",
- Version: "test",
- Metadata: map[string]any{
- "str": "test",
- "num": 1.0,
- },
- }
- hbraw, err := json.Marshal(hb)
- if err != nil {
- t.Errorf("failed to marshal heartbeat: %s", err.Error())
- }
- heartbeatTests := []decoderTestCase[heartbeat.Heartbeat]{
- {
- name: "heartbeat valid",
- data: hbraw,
- want: &hb,
- wantErr: false,
- },
- {
- name: "heartbeat invalid",
- data: badBytes,
- want: nil,
- wantErr: true,
- },
- }
- testDecoder(t, JSONDecoder, heartbeatTests)
- }
- func TestGzipDecoder(t *testing.T) {
- badBytes := generateBadBytes()
- now := time.Now().UTC().Truncate(24 * time.Hour)
- start := now.Add(-(24 * 5) * time.Hour)
- diag := diagnostics.DiagnosticResult{
- ID: "diagnosticID",
- Name: "diagnisticName",
- Description: "Test Diagnostic",
- Category: "test",
- Timestamp: start,
- Error: "test",
- Details: map[string]any{
- "str": "test",
- "num": 1.0,
- },
- }
- diagRaw, err := json.Marshal(diag)
- if err != nil {
- t.Errorf("failed to marshal diagnostic: %s", err.Error())
- }
- diagCompressed, err := gZipEncode(diagRaw)
- if err != nil {
- t.Errorf("failed to compress diagnostic: %s", err.Error())
- }
- badCompressed, err := gZipEncode(badBytes)
- if err != nil {
- t.Errorf("failed to compress bad bytes: %s", err.Error())
- }
- diagnosticTests := []decoderTestCase[diagnostics.DiagnosticResult]{
- {
- name: "diagnostic valid",
- data: diagCompressed,
- want: &diag,
- wantErr: false,
- },
- {
- name: "diagnostic invalid",
- data: badCompressed,
- want: nil,
- wantErr: true,
- },
- {
- name: "diagnostic bypass valid",
- data: diagRaw,
- want: &diag,
- wantErr: false,
- },
- {
- name: "diagnostic bypass invalid",
- data: badBytes,
- want: nil,
- wantErr: true,
- },
- }
- testDecoder(t, GetGzipDecoder[diagnostics.DiagnosticResult](JSONDecoder), diagnosticTests)
- }
- func TestProtobufDecoder(t *testing.T) {
- badBytes := generateBadBytes()
- now := time.Now().UTC().Truncate(24 * time.Hour)
- start := now.Add(-(24 * 5) * time.Hour)
- customCostSet := model.GenerateMockCustomCostSet(start, start.Add(24*time.Hour))
- customCostSetRaw, err := proto.Marshal(customCostSet)
- if err != nil {
- t.Errorf("failed to marshal custom cost set: %s", err.Error())
- }
- customCostTests := []decoderTestCase[pb.CustomCostResponse]{
- {
- name: "custom cost valid",
- data: customCostSetRaw,
- want: customCostSet,
- wantErr: false,
- },
- {
- name: "custom cost invalid",
- data: badBytes,
- want: nil,
- wantErr: true,
- },
- }
- testProtoBufDecoder(t, ProtobufDecoder, customCostTests)
- labelsResponse := model.GenerateMockLabelResponse(start, pb.Resolution_RESOLUTION_1D)
- labelsResponseRaw, err := proto.Marshal(labelsResponse)
- if err != nil {
- t.Errorf("failed to marshal custom cost set: %s", err.Error())
- }
- labelsResponseTests := []decoderTestCase[pb.LabelsResponse]{
- {
- name: "labels response valid",
- data: labelsResponseRaw,
- want: labelsResponse,
- wantErr: false,
- },
- {
- name: "labels response invalid",
- data: badBytes,
- want: nil,
- wantErr: true,
- },
- }
- testProtoBufDecoder(t, ProtobufDecoder, labelsResponseTests)
- }
- func testProtoBufDecoder[T any, U ProtoMessagePtr[T]](t *testing.T, decoder Decoder[T], testCases []decoderTestCase[T]) {
- for _, tt := range testCases {
- t.Run(tt.name, func(t *testing.T) {
- got, err := decoder(tt.data)
- if (err != nil) != tt.wantErr {
- t.Errorf("Decoder() error = %v, wantErr %v", err, tt.wantErr)
- if err != nil {
- t.Errorf("Error: %s", err.Error())
- }
- return
- }
- if !proto.Equal(U(got), U(tt.want)) {
- t.Errorf("Decoder() got = %v, want %v", got, tt.want)
- }
- })
- }
- }
- func testDecoder[T any](t *testing.T, decoder Decoder[T], testCases []decoderTestCase[T]) {
- for _, tt := range testCases {
- t.Run(tt.name, func(t *testing.T) {
- got, err := decoder(tt.data)
- if (err != nil) != tt.wantErr {
- t.Errorf("Decoder() error = %v, wantErr %v", err, tt.wantErr)
- if err != nil {
- t.Errorf("Error: %s", err.Error())
- }
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("Decoder() got = %v, want %v", got, tt.want)
- }
- })
- }
- }
|