Skip to content

Commit

Permalink
unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Sajit Kunnumkal <[email protected]>
  • Loading branch information
sajit committed Jan 28, 2025
1 parent 7ec888a commit e3300cb
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 12 deletions.
Binary file added pkg/plugins/snowflake/cmd/main/main
Binary file not shown.
25 changes: 14 additions & 11 deletions pkg/plugins/snowflake/cmd/main/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func GetInvoices(snowflakeClient SnowflakeClient) ([]snowflakeplugin.LineItem, e
rows, err := snowflakeClient.ExecuteQuery(query)
if err != nil {

log.Fatalf("Query execution failed:", err)
log.Fatalf("Query execution failed: %v", err)
return nil, err
}
defer rows.Close()
Expand All @@ -103,7 +103,7 @@ func GetInvoices(snowflakeClient SnowflakeClient) ([]snowflakeplugin.LineItem, e
var date string

if err := rows.Scan(&date, &warehouse, &credits); err != nil {
log.Fatalf("", err)
log.Fatalf("%v", err)
}

lineItem := snowflakeplugin.LineItem{
Expand All @@ -115,8 +115,10 @@ func GetInvoices(snowflakeClient SnowflakeClient) ([]snowflakeplugin.LineItem, e
lineItems = append(lineItems, lineItem)
}

if err = rows.Err(); err != nil {
log.Fatalf("", err)
sqlError := rows.Err()
if sqlError != nil {
log.Fatalf("%v", sqlError)
return nil, sqlError
}

return lineItems, nil
Expand Down Expand Up @@ -145,7 +147,7 @@ func main() {
client, err := NewSnowflakeClient(snowflakeConfig)

if err != nil {
log.Fatalf("Failed to create Snowflake client:", err)
log.Fatalf("Failed to create Snowflake client: %v", err)
}
snowflakeCostSource := SnowflakeCostSource{
snowflakeClient: client,
Expand Down Expand Up @@ -215,13 +217,14 @@ func (s *SnowflakeCostSource) GetCustomCosts(req *pb.CustomCostRequest) []*pb.Cu
func filterLineItemsByWindow(win *opencost.Window, lineItems []snowflakeplugin.LineItem) []*pb.CustomCost {
var filteredItems []*pb.CustomCost
for _, li := range lineItems {
if li.Date == win.Start().Format("2006-01-02 15:04:05") {
cost := &pb.CustomCost{
UsageQuantity: li.CreditUsed,
ResourceName: li.WarehouseName,
}
filteredItems = append(filteredItems, cost)
log.Debugf("Window Start: %s ", win.Start().Format("2006-01-02 15:04:05"))

cost := &pb.CustomCost{
UsageQuantity: li.CreditUsed,
ResourceName: li.WarehouseName,
}
filteredItems = append(filteredItems, cost)

}
return filteredItems
}
Expand Down
166 changes: 166 additions & 0 deletions pkg/plugins/snowflake/cmd/main/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package main

import (
"errors"
"testing"
"time"

snowflakeplugin "github.com/opencost/opencost-plugins/pkg/plugins/snowflake/plugin"
"github.com/opencost/opencost/core/pkg/model/pb"
"github.com/opencost/opencost/core/pkg/opencost"
"github.com/stretchr/testify/assert"
"google.golang.org/protobuf/types/known/timestamppb"

"github.com/DATA-DOG/go-sqlmock" // For mocking SQL database
)

// TestGetInvoices function
func TestGetInvoices(t *testing.T) {
// Create a mocked database connection
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("Error initializing sqlmock: %v", err)
}
defer db.Close()

// Convert MockRows to *sql.Rows

expectedQuery := `(?s)SELECT start_time, warehouse_name, credits_used_compute FROM snowflake\.account_usage\.warehouse_metering_history WHERE start_time >= DATEADD\(day, -m, CURRENT_TIMESTAMP\(\)\) AND warehouse_id > 0 -- Skip pseudo-VWs such as "CLOUD_SERVICES_ONLY" ORDER BY 1 DESC, 2;`

rows := sqlmock.NewRows([]string{"Date", "WarehouseName", "Credits"}).
AddRow("2025-01-23", "ANALYTICS_VW", 123.45).
AddRow("2025-01-22", "LOADING_VW", 75)

// Expect the query and provide the mock response
mock.ExpectQuery(expectedQuery).WillReturnRows(rows)

// Create the SnowflakeClient with the mocked db
mockClient := &snowflakeClient{db: db}

// Test the function
invoices, err := GetInvoices(mockClient)

// Assertions
assert.NoError(t, err)
assert.Len(t, invoices, 2)

expectedInvoices := []snowflakeplugin.LineItem{
{WarehouseName: "ANALYTICS_VW", CreditUsed: 123.45, Date: "2025-01-23"},
{WarehouseName: "LOADING_VW", CreditUsed: 75, Date: "2025-01-22"},
}
assert.Equal(t, expectedInvoices, invoices)

}

func TestExecuteQueryWithRowError(t *testing.T) {
// Create a mocked database connection
db, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("Error initializing sqlmock: %v", err)
}
defer db.Close()

// Define the query
query := "SELECT start_time, warehouse_name, credits_used_compute FROM warehouse_metering_history"

// Create mock rows with an error injected
rows := sqlmock.NewRows([]string{"start_time", "warehouse_name", "credits_used_compute"}).
AddRow("2025-01-28T16:00:00Z", "WH1", 123.45).
AddRow("2025-01-28T15:00:00Z", "WH2", 678.90).
RowError(1, errors.New("simulated row error")) // Inject error at row index 1

// Expect the query and provide the mock response
mock.ExpectQuery(query).WillReturnRows(rows)

// Create the SnowflakeClient with the mocked db
client := &snowflakeClient{db: db}

// Call ExecuteQuery
result, err := client.ExecuteQuery(query)
if err != nil {
t.Fatalf("ExecuteQuery failed: %v", err)
}
defer result.Close()

// Validate the results
var (
startTime string
warehouseName string
credits float64
)

for result.Next() {
if err := result.Scan(&startTime, &warehouseName, &credits); err != nil {
t.Fatalf("Error scanning row: %v", err)
}
}

// Check for row errors
if err := result.Err(); err == nil {
t.Errorf("Expected an error from result.Err(), but got nil")
} else if err.Error() != "simulated row error" {
t.Errorf("Unexpected error message from result.Err(): %v", err)
}

// Verify that all expectations were met
if err := mock.ExpectationsWereMet(); err != nil {
t.Errorf("SQL expectations were not met: %v", err)
}
}

func TestGetCustomCosts(t *testing.T) {
assert.Equal(t, 0, 0)
}

func TestFilterLineItemsByWindow(t *testing.T) {
assert.Equal(t, 0, 0)
}

func TestGetSnowflakeCostsForWindow(t *testing.T) {

// Create a mocked database connection
db, _, err := sqlmock.New()
if err != nil {
t.Fatalf("Error initializing sqlmock: %v", err)
}
defer db.Close()

// Create the SnowflakeClient with the mocked db
mockClient := &snowflakeClient{db: db}
// Create SnowflakeCostSource
snowflakeCostSource := SnowflakeCostSource{
snowflakeClient: mockClient,
}

// Define the window
startTime := time.Date(2025, 1, 20, 0, 0, 0, 0, time.UTC)
endTime := time.Date(2025, 1, 25, 0, 0, 0, 0, time.UTC)
window := opencost.NewWindow(&startTime, &endTime)

// Fetch line items
lineItems := []snowflakeplugin.LineItem{
{WarehouseName: "ANALYTICS_VW", CreditUsed: 123.45, Date: "2025-01-23"},
{WarehouseName: "LOADING_VW", CreditUsed: 75, Date: "2025-01-22"},
}

// Call GetSnowflakeCostsForWindow
result := snowflakeCostSource.GetSnowflakeCostsForWindow(&window, lineItems)

// Assertions
assert.NotNil(t, result)
assert.Equal(t, "data_storage", result.CostSource)
assert.Equal(t, "snowflake", result.Domain)
assert.Equal(t, "v1", result.Version)
assert.Equal(t, "USD", result.Currency)
assert.Equal(t, timestamppb.New(startTime), result.Start)
assert.Equal(t, timestamppb.New(endTime), result.End)
assert.Empty(t, result.Errors)
assert.Len(t, result.Costs, 2)

expectedCosts := []*pb.CustomCost{
{UsageQuantity: 123.45, ResourceName: "ANALYTICS_VW"},
{UsageQuantity: 75, ResourceName: "LOADING_VW"},
}
assert.Equal(t, expectedCosts, result.Costs)

}
7 changes: 6 additions & 1 deletion pkg/plugins/snowflake/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ require (
github.com/hashicorp/go-plugin v1.6.1
github.com/opencost/opencost-plugins/common v0.0.0-00010101000000-000000000000
github.com/opencost/opencost/core v0.0.0-20250117200701-47c4b6817505
github.com/stretchr/testify v1.9.0
google.golang.org/protobuf v1.33.0

)

require (
github.com/DATA-DOG/go-sqlmock v1.5.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
Expand All @@ -37,13 +40,14 @@ require (
github.com/oklog/run v1.1.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml v1.9.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rs/zerolog v1.26.1 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.8.1 // indirect
github.com/stretchr/testify v1.9.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326 // indirect
golang.org/x/net v0.23.0 // indirect
Expand All @@ -55,6 +59,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.25.3 // indirect
k8s.io/apimachinery v0.25.3 // indirect
k8s.io/klog/v2 v2.80.0 // indirect
Expand Down
5 changes: 5 additions & 0 deletions pkg/plugins/snowflake/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
Expand Down Expand Up @@ -199,6 +201,7 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
Expand Down Expand Up @@ -281,6 +284,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
Expand Down

0 comments on commit e3300cb

Please sign in to comment.