| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372 |
- package alibaba
- import (
- "testing"
- "github.com/aliyun/alibaba-cloud-sdk-go/services/bssopenapi"
- "github.com/opencost/opencost/core/pkg/opencost"
- "github.com/opencost/opencost/pkg/cloud"
- )
- func TestBoaQuerier_GetStatus(t *testing.T) {
- testCases := map[string]struct {
- querier BoaQuerier
- expectedStatus cloud.ConnectionStatus
- }{
- "initial status": {
- querier: BoaQuerier{},
- expectedStatus: cloud.InitialStatus,
- },
- "existing status": {
- querier: BoaQuerier{
- ConnectionStatus: cloud.SuccessfulConnection,
- },
- expectedStatus: cloud.SuccessfulConnection,
- },
- }
- for name, testCase := range testCases {
- t.Run(name, func(t *testing.T) {
- status := testCase.querier.GetStatus()
- if status != testCase.expectedStatus {
- t.Errorf("expected status %v, got %v", testCase.expectedStatus, status)
- }
- })
- }
- }
- func TestBoaQuerier_Equals(t *testing.T) {
- baseQuerier := BoaQuerier{
- BOAConfiguration: BOAConfiguration{
- Account: "account1",
- Region: "region1",
- Authorizer: &AccessKey{
- AccessKeyID: "id1",
- AccessKeySecret: "secret1",
- },
- },
- ConnectionStatus: cloud.SuccessfulConnection,
- }
- testCases := map[string]struct {
- left BoaQuerier
- right cloud.Config
- expected bool
- }{
- "matching queriers": {
- left: baseQuerier,
- right: &BoaQuerier{
- BOAConfiguration: BOAConfiguration{
- Account: "account1",
- Region: "region1",
- Authorizer: &AccessKey{
- AccessKeyID: "id1",
- AccessKeySecret: "secret1",
- },
- },
- ConnectionStatus: cloud.SuccessfulConnection,
- },
- expected: true,
- },
- "different config": {
- left: baseQuerier,
- right: &BOAConfiguration{
- Account: "account1",
- Region: "region1",
- },
- expected: false,
- },
- "nil config": {
- left: baseQuerier,
- right: nil,
- expected: false,
- },
- "different account": {
- left: baseQuerier,
- right: &BoaQuerier{
- BOAConfiguration: BOAConfiguration{
- Account: "account2",
- Region: "region1",
- Authorizer: &AccessKey{
- AccessKeyID: "id1",
- AccessKeySecret: "secret1",
- },
- },
- },
- expected: false,
- },
- }
- for name, testCase := range testCases {
- t.Run(name, func(t *testing.T) {
- result := testCase.left.Equals(testCase.right)
- if result != testCase.expected {
- t.Errorf("expected %t, got %t", testCase.expected, result)
- }
- })
- }
- }
- func TestBoaQuerier_QueryInstanceBill(t *testing.T) {
- // This test would require a mock BSS client
- // For now, we'll test the function signature and basic error handling
- querier := BoaQuerier{
- BOAConfiguration: BOAConfiguration{
- Account: "test-account",
- Region: "test-region",
- Authorizer: &AccessKey{
- AccessKeyID: "test-id",
- AccessKeySecret: "test-secret",
- },
- },
- }
- // Test with nil client (should panic or return error)
- defer func() {
- if r := recover(); r == nil {
- // Expected to panic with nil client
- }
- }()
- _, err := querier.QueryInstanceBill(nil, true, "https", "DAILY", "2023-01", "2023-01-01", 1)
- if err == nil {
- t.Error("expected error with nil client")
- }
- }
- func TestBoaQuerier_QueryBoaPaginated(t *testing.T) {
- querier := BoaQuerier{
- BOAConfiguration: BOAConfiguration{
- Account: "test-account",
- Region: "test-region",
- Authorizer: &AccessKey{
- AccessKeyID: "test-id",
- AccessKeySecret: "test-secret",
- },
- },
- }
- // Test with nil client - this will panic, so we need to recover
- defer func() {
- if r := recover(); r == nil {
- t.Error("expected panic with nil client")
- }
- }()
- querier.QueryBoaPaginated(nil, true, "https", "DAILY", "2023-01", "2023-01-01", func(*bssopenapi.QueryInstanceBillResponse) bool {
- return true
- })
- }
- func TestGetBoaQueryInstanceBillFunc(t *testing.T) {
- testCases := map[string]struct {
- response *bssopenapi.QueryInstanceBillResponse
- expectedReturn bool
- callCount int
- }{
- "nil response": {
- response: nil,
- expectedReturn: false,
- callCount: 0,
- },
- "empty response": {
- response: &bssopenapi.QueryInstanceBillResponse{},
- expectedReturn: false,
- callCount: 0,
- },
- "valid response with items": {
- response: &bssopenapi.QueryInstanceBillResponse{},
- expectedReturn: false,
- callCount: 0,
- },
- }
- for name, testCase := range testCases {
- t.Run(name, func(t *testing.T) {
- callCount := 0
- handler := func(item bssopenapi.Item) error {
- callCount++
- return nil
- }
- processor := GetBoaQueryInstanceBillFunc(handler, "2023-01-01")
- result := processor(testCase.response)
- if result != testCase.expectedReturn {
- t.Errorf("expected return %t, got %t", testCase.expectedReturn, result)
- }
- if callCount != testCase.callCount {
- t.Errorf("expected %d calls to handler, got %d", testCase.callCount, callCount)
- }
- })
- }
- }
- func TestSelectAlibabaCategory(t *testing.T) {
- testCases := map[string]struct {
- item bssopenapi.Item
- expectedCategory string
- }{
- "empty item": {
- item: bssopenapi.Item{},
- expectedCategory: opencost.OtherCategory,
- },
- "node instance": {
- item: bssopenapi.Item{
- InstanceID: "i-test123",
- },
- expectedCategory: opencost.ComputeCategory,
- },
- "disk instance": {
- item: bssopenapi.Item{
- InstanceID: "d-test123",
- },
- expectedCategory: opencost.StorageCategory,
- },
- "network usage": {
- item: bssopenapi.Item{
- UsageUnit: "piece",
- },
- expectedCategory: opencost.NetworkCategory,
- },
- "SLB product": {
- item: bssopenapi.Item{
- ProductCode: "slb",
- },
- expectedCategory: opencost.NetworkCategory,
- },
- "EIP product": {
- item: bssopenapi.Item{
- ProductCode: "eip",
- },
- expectedCategory: opencost.NetworkCategory,
- },
- "NIS product": {
- item: bssopenapi.Item{
- ProductCode: "nis",
- },
- expectedCategory: opencost.NetworkCategory,
- },
- "GTM product": {
- item: bssopenapi.Item{
- ProductCode: "gtm",
- },
- expectedCategory: opencost.NetworkCategory,
- },
- "ECS product": {
- item: bssopenapi.Item{
- ProductCode: "ecs",
- },
- expectedCategory: opencost.ComputeCategory,
- },
- "EDS product": {
- item: bssopenapi.Item{
- ProductCode: "eds",
- },
- expectedCategory: opencost.ComputeCategory,
- },
- "SAS product": {
- item: bssopenapi.Item{
- ProductCode: "sas",
- },
- expectedCategory: opencost.ComputeCategory,
- },
- "ACK product": {
- item: bssopenapi.Item{
- ProductCode: "ack",
- },
- expectedCategory: opencost.ManagementCategory,
- },
- "EBS product": {
- item: bssopenapi.Item{
- ProductCode: "ebs",
- },
- expectedCategory: opencost.StorageCategory,
- },
- "OSS product": {
- item: bssopenapi.Item{
- ProductCode: "oss",
- },
- expectedCategory: opencost.StorageCategory,
- },
- "SCU product": {
- item: bssopenapi.Item{
- ProductCode: "scu",
- },
- expectedCategory: opencost.StorageCategory,
- },
- "unknown product": {
- item: bssopenapi.Item{
- ProductCode: "unknown",
- },
- expectedCategory: opencost.OtherCategory,
- },
- "case insensitive product code": {
- item: bssopenapi.Item{
- ProductCode: "SLB",
- },
- expectedCategory: opencost.NetworkCategory,
- },
- "node with network usage (node takes precedence)": {
- item: bssopenapi.Item{
- InstanceID: "i-test123",
- UsageUnit: "piece",
- },
- expectedCategory: opencost.ComputeCategory,
- },
- "disk with network usage (disk takes precedence)": {
- item: bssopenapi.Item{
- InstanceID: "d-test123",
- UsageUnit: "piece",
- },
- expectedCategory: opencost.StorageCategory,
- },
- }
- for name, testCase := range testCases {
- t.Run(name, func(t *testing.T) {
- result := SelectAlibabaCategory(testCase.item)
- if result != testCase.expectedCategory {
- t.Errorf("expected category %s, got %s", testCase.expectedCategory, result)
- }
- })
- }
- }
- func TestBoaQuerier_Integration(t *testing.T) {
- // Test that BoaQuerier properly embeds BOAConfiguration
- querier := BoaQuerier{
- BOAConfiguration: BOAConfiguration{
- Account: "test-account",
- Region: "test-region",
- Authorizer: &AccessKey{
- AccessKeyID: "test-id",
- AccessKeySecret: "test-secret",
- },
- },
- ConnectionStatus: cloud.SuccessfulConnection,
- }
- // Test that we can access BOAConfiguration methods
- if querier.Account != "test-account" {
- t.Errorf("expected account test-account, got %s", querier.Account)
- }
- if querier.Region != "test-region" {
- t.Errorf("expected region test-region, got %s", querier.Region)
- }
- // Test Key method from embedded BOAConfiguration
- key := querier.Key()
- expectedKey := "test-account/test-region"
- if key != expectedKey {
- t.Errorf("expected key %s, got %s", expectedKey, key)
- }
- // Test Provider method from embedded BOAConfiguration
- provider := querier.Provider()
- if provider != opencost.AlibabaProvider {
- t.Errorf("expected provider %s, got %s", opencost.AlibabaProvider, provider)
- }
- }
|