From 475a05a9c843c164c4712e94cb623fd4a3ae1df5 Mon Sep 17 00:00:00 2001 From: Dhanashree Phulkar Date: Mon, 10 Jun 2024 16:16:20 +0530 Subject: [PATCH 1/4] [Storage Explorer] _token_refresh_source type change --- common/oauthTOkenManager_test.go | 128 +++++++++++++++++++++++++++++++ common/oauthTokenManager.go | 29 ++++++- 2 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 common/oauthTOkenManager_test.go diff --git a/common/oauthTOkenManager_test.go b/common/oauthTOkenManager_test.go new file mode 100644 index 000000000..3b2a77cb7 --- /dev/null +++ b/common/oauthTOkenManager_test.go @@ -0,0 +1,128 @@ +// Copyright © 2017 Microsoft + +// + +// Permission is hereby granted, free of charge, to any person obtaining a copy + +// of this software and associated documentation files (the "Software"), to deal + +// in the Software without restriction, including without limitation the rights + +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + +// copies of the Software, and to permit persons to whom the Software is + +// furnished to do so, subject to the following conditions: + +// + +// The above copyright notice and this permission notice shall be included in + +// all copies or substantial portions of the Software. + +// + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + +// THE SOFTWARE. + +package common + +import ( + "context" + "os" + "reflect" + "testing" +) + +func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { + type args struct { + ctx context.Context + } + tests := []struct { + name string + uotm *UserOAuthTokenManager + args args + setup func(t *testing.T) + want *OAuthTokenInfo + wantErr bool + }{ + { + name: "This UT tests if AutoLoginType filed is parsed properly from string to uint8 data type", + uotm: &UserOAuthTokenManager{}, + args: args{ + ctx: context.Background(), + }, + setup: func(t *testing.T) { + tokenInfoJSON := `{ + "access_token": "dummy_access_token", + "refresh_token": "dummy_refresh_token", + "expires_in": 0, + "expires_on": 0, + "not_before": 0, + "resource": "dummy_resource", + "token_type": "dummy_token_type", + "_tenant": "dummy_tenant", + "_ad_endpoint": "dummy_ad_endpoint", + "_token_refresh_source": "255", + "_application_id": "dummy_application_id", + "IdentityInfo": { + "_identity_client_id": "dummy_identity_client_id", + "_identity_object_id": "dummy_identity_object_id", + "_identity_msi_res_id": "dummy_identity_msi_res_id" + }, + "SPNInfo": { + "_spn_secret": "dummy_spn_secret", + "_spn_cert_path": "dummy_spn_cert_path" + } + }` + + // Set the environment variable AZCOPY_OAUTH_TOKEN_INFO + err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfoJSON) + if err != nil { + t.Fatalf("Failed to set environment variable: %v", err) + } + }, + want: &OAuthTokenInfo{ + Tenant: "dummy_tenant", + ActiveDirectoryEndpoint: "dummy_ad_endpoint", + LoginType: 255, + ApplicationID: "dummy_application_id", + IdentityInfo: IdentityInfo{ + ClientID: "dummy_identity_client_id", + ObjectID: "dummy_identity_object_id", + MSIResID: "dummy_identity_msi_res_id", + }, + SPNInfo: SPNInfo{ + Secret: "dummy_spn_secret", + CertPath: "dummy_spn_cert_path", + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + tt.setup(t) + got, err := tt.uotm.GetTokenInfo(tt.args.ctx) + if (err != nil) != tt.wantErr { + t.Errorf("UserOAuthTokenManager.GetTokenInfo() error = %v, wantErr %v", err, tt.wantErr) + return + } + if reflect.DeepEqual(got, tt.want) { + t.Errorf("UserOAuthTokenManager.GetTokenInfo() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/common/oauthTokenManager.go b/common/oauthTokenManager.go index ead150881..2d7791e9b 100644 --- a/common/oauthTokenManager.go +++ b/common/oauthTokenManager.go @@ -84,7 +84,7 @@ func newAzcopyHTTPClient() *http.Client { Timeout: 10 * time.Second, KeepAlive: 10 * time.Second, DualStack: true, - }).Dial, /*Context*/ + }).Dial, /*Context*/ MaxIdleConns: 0, // No limit MaxIdleConnsPerHost: 1000, IdleConnTimeout: 180 * time.Second, @@ -524,7 +524,7 @@ type TokenStoreCredential struct { // we do not make repeated GetToken calls. // This is a temporary fix for issue where we would request a // new token from Stg Exp even while they've not yet populated the -// tokenstore. +// tokenstore. // // This is okay because we use same credential on both source and // destination. If we move to a case where the credentials are @@ -532,7 +532,6 @@ type TokenStoreCredential struct { // // We should move to a method where the token is always read from // tokenstore, and azcopy is invoked after tokenstore is populated. -// var globalTokenStoreCredential *TokenStoreCredential var globalTsc sync.Once @@ -771,8 +770,32 @@ func (credInfo *OAuthTokenInfo) GetTokenCredential() (azcore.TokenCredential, er } } +// @brief MarshalJSON implements the json.Marshaler interface for AutoLoginType +func (alt AutoLoginType) MarshalJSON() ([]byte, error) { + str := strconv.FormatUint(uint64(alt), 10) + return json.Marshal(str) +} + +// @brief UnmarshalJSON implements the json.Unmarshaler interface for autoLoginType +func (alt *AutoLoginType) UnmarshalJSON(data []byte) (err error) { + + var autoLoginTypeStr string + if err := json.Unmarshal(data, &autoLoginTypeStr); err != nil { + return err + } + + val, err := strconv.ParseUint(autoLoginTypeStr, 10, 8) + if err != nil { + return + } + + *alt = AutoLoginType(uint8(val)) + return +} + // jsonToTokenInfo converts bytes to OAuthTokenInfo func jsonToTokenInfo(b []byte) (*OAuthTokenInfo, error) { + var OAuthTokenInfo OAuthTokenInfo if err := json.Unmarshal(b, &OAuthTokenInfo); err != nil { return nil, err From 2508c151a1c7f8b0bafff3e05bdeb435e194f1df Mon Sep 17 00:00:00 2001 From: Dhanashree Phulkar Date: Mon, 10 Jun 2024 16:16:20 +0530 Subject: [PATCH 2/4] [Storage Explorer] _token_refresh_source type change --- common/oauthTOkenManager_test.go | 110 +++++++++++++++++++++++++++++++ common/oauthTokenManager.go | 28 +++++++- 2 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 common/oauthTOkenManager_test.go diff --git a/common/oauthTOkenManager_test.go b/common/oauthTOkenManager_test.go new file mode 100644 index 000000000..d7478a746 --- /dev/null +++ b/common/oauthTOkenManager_test.go @@ -0,0 +1,110 @@ +// Copyright © 2017 Microsoft +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +package common + +import ( + "context" + "os" + "reflect" + "testing" +) + +func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { + type args struct { + ctx context.Context + } + tests := []struct { + name string + uotm *UserOAuthTokenManager + args args + setup func(t *testing.T) + want *OAuthTokenInfo + wantErr bool + }{ + { + name: "This UT tests if AutoLoginType filed is parsed properly from string to uint8 data type", + uotm: &UserOAuthTokenManager{}, + args: args{ + ctx: context.Background(), + }, + setup: func(t *testing.T) { + tokenInfoJSON := `{ + "access_token": "dummy_access_token", + "refresh_token": "dummy_refresh_token", + "expires_in": 0, + "expires_on": 0, + "not_before": 0, + "resource": "dummy_resource", + "token_type": "dummy_token_type", + "_tenant": "dummy_tenant", + "_ad_endpoint": "dummy_ad_endpoint", + "_token_refresh_source": "255", + "_application_id": "dummy_application_id", + "IdentityInfo": { + "_identity_client_id": "dummy_identity_client_id", + "_identity_object_id": "dummy_identity_object_id", + "_identity_msi_res_id": "dummy_identity_msi_res_id" + }, + "SPNInfo": { + "_spn_secret": "dummy_spn_secret", + "_spn_cert_path": "dummy_spn_cert_path" + } + }` + + // Set the environment variable AZCOPY_OAUTH_TOKEN_INFO + err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfoJSON) + if err != nil { + t.Fatalf("Failed to set environment variable: %v", err) + } + }, + want: &OAuthTokenInfo{ + Tenant: "dummy_tenant", + ActiveDirectoryEndpoint: "dummy_ad_endpoint", + LoginType: 255, + ApplicationID: "dummy_application_id", + IdentityInfo: IdentityInfo{ + ClientID: "dummy_identity_client_id", + ObjectID: "dummy_identity_object_id", + MSIResID: "dummy_identity_msi_res_id", + }, + SPNInfo: SPNInfo{ + Secret: "dummy_spn_secret", + CertPath: "dummy_spn_cert_path", + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + + tt.setup(t) + got, err := tt.uotm.GetTokenInfo(tt.args.ctx) + if (err != nil) != tt.wantErr { + t.Errorf("UserOAuthTokenManager.GetTokenInfo() error = %v, wantErr %v", err, tt.wantErr) + return + } + if reflect.DeepEqual(got, tt.want) { + t.Errorf("UserOAuthTokenManager.GetTokenInfo() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/common/oauthTokenManager.go b/common/oauthTokenManager.go index ead150881..dd061b47b 100644 --- a/common/oauthTokenManager.go +++ b/common/oauthTokenManager.go @@ -84,7 +84,7 @@ func newAzcopyHTTPClient() *http.Client { Timeout: 10 * time.Second, KeepAlive: 10 * time.Second, DualStack: true, - }).Dial, /*Context*/ + }).Dial, /*Context*/ MaxIdleConns: 0, // No limit MaxIdleConnsPerHost: 1000, IdleConnTimeout: 180 * time.Second, @@ -524,7 +524,7 @@ type TokenStoreCredential struct { // we do not make repeated GetToken calls. // This is a temporary fix for issue where we would request a // new token from Stg Exp even while they've not yet populated the -// tokenstore. +// tokenstore. // // This is okay because we use same credential on both source and // destination. If we move to a case where the credentials are @@ -532,7 +532,6 @@ type TokenStoreCredential struct { // // We should move to a method where the token is always read from // tokenstore, and azcopy is invoked after tokenstore is populated. -// var globalTokenStoreCredential *TokenStoreCredential var globalTsc sync.Once @@ -771,6 +770,29 @@ func (credInfo *OAuthTokenInfo) GetTokenCredential() (azcore.TokenCredential, er } } +// @brief MarshalJSON implements the json.Marshaler interface for AutoLoginType +func (alt AutoLoginType) MarshalJSON() ([]byte, error) { + str := strconv.FormatUint(uint64(alt), 10) + return json.Marshal(str) +} + +// @brief UnmarshalJSON implements the json.Unmarshaler interface for autoLoginType +func (alt *AutoLoginType) UnmarshalJSON(data []byte) (err error) { + + var autoLoginTypeStr string + if err := json.Unmarshal(data, &autoLoginTypeStr); err != nil { + return err + } + + val, err := strconv.ParseUint(autoLoginTypeStr, 10, 8) + if err != nil { + return + } + + *alt = AutoLoginType(uint8(val)) + return +} + // jsonToTokenInfo converts bytes to OAuthTokenInfo func jsonToTokenInfo(b []byte) (*OAuthTokenInfo, error) { var OAuthTokenInfo OAuthTokenInfo From 56d5d3bda96a939c2b5d6cb87b3c68d17b9da81c Mon Sep 17 00:00:00 2001 From: Dhanashree Phulkar Date: Wed, 12 Jun 2024 09:56:50 +0530 Subject: [PATCH 3/4] incorporated review comments --- common/environment.go | 6 +- common/oauthTokenManager_test.go | 163 ++++++++++++------------------- 2 files changed, 69 insertions(+), 100 deletions(-) diff --git a/common/environment.go b/common/environment.go index f884aeca2..5a4b7f3d0 100644 --- a/common/environment.go +++ b/common/environment.go @@ -22,6 +22,7 @@ package common import ( "encoding/json" + "fmt" "reflect" "runtime" "strings" @@ -133,11 +134,14 @@ func (d *AutoLoginType) UnmarshalJSON(data []byte) error { } // Handle numeric values if numValue, ok := v.(float64); ok { + if numValue < 0 || numValue > 255 { + return fmt.Errorf("value out of range for _token_source_refresh: %v", numValue) + } *d = AutoLoginType(uint8(numValue)) return nil } - return nil + return fmt.Errorf("unsupported type for AutoLoginType: %T", v) } func ValidAutoLoginTypes() []string { diff --git a/common/oauthTokenManager_test.go b/common/oauthTokenManager_test.go index 3d6d3c324..75f7f8732 100644 --- a/common/oauthTokenManager_test.go +++ b/common/oauthTokenManager_test.go @@ -22,31 +22,14 @@ package common import ( "context" + "fmt" "os" "reflect" + "strconv" "testing" ) -func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { - type args struct { - ctx context.Context - } - tests := []struct { - name string - uotm *UserOAuthTokenManager - args args - setup func(t *testing.T) - want *OAuthTokenInfo - wantErr bool - }{ - { - name: "This UT tests if AutoLoginType filled is parsed properly from string to uint8 data type", - uotm: &UserOAuthTokenManager{}, - args: args{ - ctx: context.Background(), - }, - setup: func(t *testing.T) { - tokenInfoJSON := `{ +const tokenInfoJson = `{ "access_token": "dummy_access_token", "refresh_token": "dummy_refresh_token", "expires_in": 0, @@ -56,7 +39,7 @@ func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { "token_type": "dummy_token_type", "_tenant": "dummy_tenant", "_ad_endpoint": "dummy_ad_endpoint", - "_token_refresh_source": "TokenStore", + "_token_refresh_source": %v, "_application_id": "dummy_application_id", "IdentityInfo": { "_identity_client_id": "dummy_identity_client_id", @@ -69,80 +52,83 @@ func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { } }` +var oauthTokenInfo = OAuthTokenInfo{ + Tenant: "dummy_tenant", + ActiveDirectoryEndpoint: "dummy_ad_endpoint", + LoginType: 255, + ApplicationID: "dummy_application_id", + IdentityInfo: IdentityInfo{ + ClientID: "dummy_identity_client_id", + ObjectID: "dummy_identity_object_id", + MSIResID: "dummy_identity_msi_res_id", + }, + SPNInfo: SPNInfo{ + Secret: "dummy_spn_secret", + CertPath: "dummy_spn_cert_path", + }, +} + +func formatTokenInfo(value interface{}) string { + var formattedValue string + switch v := value.(type) { + case string: + formattedValue = fmt.Sprintf("\"%s\"", v) + case int: + formattedValue = strconv.Itoa(v) + default: + formattedValue = fmt.Sprintf("%v", v) + } + return fmt.Sprintf(tokenInfoJson, formattedValue) +} + +func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { + type args struct { + ctx context.Context + } + tests := []struct { + name string + uotm *UserOAuthTokenManager + args args + setup func(t *testing.T) + want *OAuthTokenInfo + wantErr bool + }{ + { + name: "This UT tests if AutoLoginType filled is parsed properly from string to uint8 data type", + uotm: &UserOAuthTokenManager{}, + args: args{ + ctx: context.Background(), + }, + setup: func(t *testing.T) { + tokenInfo := formatTokenInfo("TokenStore") + fmt.Println(tokenInfo) + // Set the environment variable AZCOPY_OAUTH_TOKEN_INFO - err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfoJSON) + err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo) if err != nil { t.Fatalf("Failed to set environment variable: %v", err) } }, - want: &OAuthTokenInfo{ - Tenant: "dummy_tenant", - ActiveDirectoryEndpoint: "dummy_ad_endpoint", - LoginType: 255, - ApplicationID: "dummy_application_id", - IdentityInfo: IdentityInfo{ - ClientID: "dummy_identity_client_id", - ObjectID: "dummy_identity_object_id", - MSIResID: "dummy_identity_msi_res_id", - }, - SPNInfo: SPNInfo{ - Secret: "dummy_spn_secret", - CertPath: "dummy_spn_cert_path", - }, - }, + want: &oauthTokenInfo, wantErr: false, }, { - name: "This UT tests if AutoLoginType filled is parsed properly to uint8 data type", + name: "This UT tests if AutoLoginType filled is assigned properly to uint8 data type", uotm: &UserOAuthTokenManager{}, args: args{ ctx: context.Background(), }, setup: func(t *testing.T) { - tokenInfoJSON := `{ - "access_token": "dummy_access_token", - "refresh_token": "dummy_refresh_token", - "expires_in": 0, - "expires_on": 0, - "not_before": 0, - "resource": "dummy_resource", - "token_type": "dummy_token_type", - "_tenant": "dummy_tenant", - "_ad_endpoint": "dummy_ad_endpoint", - "_token_refresh_source": 255, - "_application_id": "dummy_application_id", - "IdentityInfo": { - "_identity_client_id": "dummy_identity_client_id", - "_identity_object_id": "dummy_identity_object_id", - "_identity_msi_res_id": "dummy_identity_msi_res_id" - }, - "SPNInfo": { - "_spn_secret": "dummy_spn_secret", - "_spn_cert_path": "dummy_spn_cert_path" - } - }` + tokenInfo := formatTokenInfo(255) + fmt.Println(tokenInfo) // Set the environment variable AZCOPY_OAUTH_TOKEN_INFO - err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfoJSON) + err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo) if err != nil { t.Fatalf("Failed to set environment variable: %v", err) } }, - want: &OAuthTokenInfo{ - Tenant: "dummy_tenant", - ActiveDirectoryEndpoint: "dummy_ad_endpoint", - LoginType: 255, - ApplicationID: "dummy_application_id", - IdentityInfo: IdentityInfo{ - ClientID: "dummy_identity_client_id", - ObjectID: "dummy_identity_object_id", - MSIResID: "dummy_identity_msi_res_id", - }, - SPNInfo: SPNInfo{ - Secret: "dummy_spn_secret", - CertPath: "dummy_spn_cert_path", - }, - }, + want: &oauthTokenInfo, wantErr: false, }, { @@ -152,31 +138,10 @@ func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { ctx: context.Background(), }, setup: func(t *testing.T) { - tokenInfoJSON := `{ - "access_token": "dummy_access_token", - "refresh_token": "dummy_refresh_token", - "expires_in": 0, - "expires_on": 0, - "not_before": 0, - "resource": "dummy_resource", - "token_type": "dummy_token_type", - "_tenant": "dummy_tenant", - "_ad_endpoint": "dummy_ad_endpoint", - "_token_refresh_source": 2er25, - "_application_id": "dummy_application_id", - "IdentityInfo": { - "_identity_client_id": "dummy_identity_client_id", - "_identity_object_id": "dummy_identity_object_id", - "_identity_msi_res_id": "dummy_identity_msi_res_id" - }, - "SPNInfo": { - "_spn_secret": "dummy_spn_secret", - "_spn_cert_path": "dummy_spn_cert_path" - } - }` + tokenInfo := formatTokenInfo("2gd6") // Set the environment variable AZCOPY_OAUTH_TOKEN_INFO - err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfoJSON) + err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo) if err != nil { t.Fatalf("Failed to set environment variable: %v", err) } From c41e36cac3bbd602982ebc31a8fe706208f8203d Mon Sep 17 00:00:00 2001 From: Dhanashree Phulkar Date: Wed, 12 Jun 2024 09:56:50 +0530 Subject: [PATCH 4/4] incorporated review comments --- common/environment.go | 6 +- common/oauthTokenManager_test.go | 183 ++++++++++++++----------------- 2 files changed, 88 insertions(+), 101 deletions(-) diff --git a/common/environment.go b/common/environment.go index f884aeca2..5a4b7f3d0 100644 --- a/common/environment.go +++ b/common/environment.go @@ -22,6 +22,7 @@ package common import ( "encoding/json" + "fmt" "reflect" "runtime" "strings" @@ -133,11 +134,14 @@ func (d *AutoLoginType) UnmarshalJSON(data []byte) error { } // Handle numeric values if numValue, ok := v.(float64); ok { + if numValue < 0 || numValue > 255 { + return fmt.Errorf("value out of range for _token_source_refresh: %v", numValue) + } *d = AutoLoginType(uint8(numValue)) return nil } - return nil + return fmt.Errorf("unsupported type for AutoLoginType: %T", v) } func ValidAutoLoginTypes() []string { diff --git a/common/oauthTokenManager_test.go b/common/oauthTokenManager_test.go index 3d6d3c324..8f00fbffd 100644 --- a/common/oauthTokenManager_test.go +++ b/common/oauthTokenManager_test.go @@ -22,31 +22,14 @@ package common import ( "context" + "fmt" "os" "reflect" + "strconv" "testing" ) -func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { - type args struct { - ctx context.Context - } - tests := []struct { - name string - uotm *UserOAuthTokenManager - args args - setup func(t *testing.T) - want *OAuthTokenInfo - wantErr bool - }{ - { - name: "This UT tests if AutoLoginType filled is parsed properly from string to uint8 data type", - uotm: &UserOAuthTokenManager{}, - args: args{ - ctx: context.Background(), - }, - setup: func(t *testing.T) { - tokenInfoJSON := `{ +const tokenInfoJson = `{ "access_token": "dummy_access_token", "refresh_token": "dummy_refresh_token", "expires_in": 0, @@ -56,7 +39,7 @@ func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { "token_type": "dummy_token_type", "_tenant": "dummy_tenant", "_ad_endpoint": "dummy_ad_endpoint", - "_token_refresh_source": "TokenStore", + "_token_refresh_source": %v, "_application_id": "dummy_application_id", "IdentityInfo": { "_identity_client_id": "dummy_identity_client_id", @@ -69,114 +52,114 @@ func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { } }` +var oauthTokenInfo = OAuthTokenInfo{ + Tenant: "dummy_tenant", + ActiveDirectoryEndpoint: "dummy_ad_endpoint", + LoginType: 255, + ApplicationID: "dummy_application_id", + IdentityInfo: IdentityInfo{ + ClientID: "dummy_identity_client_id", + ObjectID: "dummy_identity_object_id", + MSIResID: "dummy_identity_msi_res_id", + }, + SPNInfo: SPNInfo{ + Secret: "dummy_spn_secret", + CertPath: "dummy_spn_cert_path", + }, +} + +func formatTokenInfo(value interface{}) string { + var formattedValue string + switch v := value.(type) { + case string: + formattedValue = fmt.Sprintf("\"%s\"", v) + case int: + formattedValue = strconv.Itoa(v) + default: + formattedValue = fmt.Sprintf("%v", v) + } + return fmt.Sprintf(tokenInfoJson, formattedValue) +} + +func TestUserOAuthTokenManager_GetTokenInfo(t *testing.T) { + type args struct { + ctx context.Context + } + tests := []struct { + name string + uotm *UserOAuthTokenManager + args args + setup func(t *testing.T) + want *OAuthTokenInfo + wantErr bool + }{ + { + name: "This UT tests if AutoLoginType filled is parsed properly from string to uint8 data type", + uotm: &UserOAuthTokenManager{}, + args: args{ + ctx: context.Background(), + }, + setup: func(t *testing.T) { + tokenInfo := formatTokenInfo("TokenStore") + fmt.Println(tokenInfo) + // Set the environment variable AZCOPY_OAUTH_TOKEN_INFO - err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfoJSON) + err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo) if err != nil { t.Fatalf("Failed to set environment variable: %v", err) } }, - want: &OAuthTokenInfo{ - Tenant: "dummy_tenant", - ActiveDirectoryEndpoint: "dummy_ad_endpoint", - LoginType: 255, - ApplicationID: "dummy_application_id", - IdentityInfo: IdentityInfo{ - ClientID: "dummy_identity_client_id", - ObjectID: "dummy_identity_object_id", - MSIResID: "dummy_identity_msi_res_id", - }, - SPNInfo: SPNInfo{ - Secret: "dummy_spn_secret", - CertPath: "dummy_spn_cert_path", - }, - }, + want: &oauthTokenInfo, wantErr: false, }, { - name: "This UT tests if AutoLoginType filled is parsed properly to uint8 data type", + name: "This UT tests if AutoLoginType filled is assigned properly to uint8 data type", uotm: &UserOAuthTokenManager{}, args: args{ ctx: context.Background(), }, setup: func(t *testing.T) { - tokenInfoJSON := `{ - "access_token": "dummy_access_token", - "refresh_token": "dummy_refresh_token", - "expires_in": 0, - "expires_on": 0, - "not_before": 0, - "resource": "dummy_resource", - "token_type": "dummy_token_type", - "_tenant": "dummy_tenant", - "_ad_endpoint": "dummy_ad_endpoint", - "_token_refresh_source": 255, - "_application_id": "dummy_application_id", - "IdentityInfo": { - "_identity_client_id": "dummy_identity_client_id", - "_identity_object_id": "dummy_identity_object_id", - "_identity_msi_res_id": "dummy_identity_msi_res_id" - }, - "SPNInfo": { - "_spn_secret": "dummy_spn_secret", - "_spn_cert_path": "dummy_spn_cert_path" - } - }` + tokenInfo := formatTokenInfo(255) + fmt.Println(tokenInfo) // Set the environment variable AZCOPY_OAUTH_TOKEN_INFO - err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfoJSON) + err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo) if err != nil { t.Fatalf("Failed to set environment variable: %v", err) } }, - want: &OAuthTokenInfo{ - Tenant: "dummy_tenant", - ActiveDirectoryEndpoint: "dummy_ad_endpoint", - LoginType: 255, - ApplicationID: "dummy_application_id", - IdentityInfo: IdentityInfo{ - ClientID: "dummy_identity_client_id", - ObjectID: "dummy_identity_object_id", - MSIResID: "dummy_identity_msi_res_id", - }, - SPNInfo: SPNInfo{ - Secret: "dummy_spn_secret", - CertPath: "dummy_spn_cert_path", - }, - }, + want: &oauthTokenInfo, wantErr: false, }, { - name: "This UT tests if _token_refresh_source fails to parse due to invalid type", + name: "This UT tests if _token_refresh_source fails to parse due to invalid string type", uotm: &UserOAuthTokenManager{}, args: args{ ctx: context.Background(), }, setup: func(t *testing.T) { - tokenInfoJSON := `{ - "access_token": "dummy_access_token", - "refresh_token": "dummy_refresh_token", - "expires_in": 0, - "expires_on": 0, - "not_before": 0, - "resource": "dummy_resource", - "token_type": "dummy_token_type", - "_tenant": "dummy_tenant", - "_ad_endpoint": "dummy_ad_endpoint", - "_token_refresh_source": 2er25, - "_application_id": "dummy_application_id", - "IdentityInfo": { - "_identity_client_id": "dummy_identity_client_id", - "_identity_object_id": "dummy_identity_object_id", - "_identity_msi_res_id": "dummy_identity_msi_res_id" - }, - "SPNInfo": { - "_spn_secret": "dummy_spn_secret", - "_spn_cert_path": "dummy_spn_cert_path" - } - }` + tokenInfo := formatTokenInfo("2gt5") + + // Set the environment variable AZCOPY_OAUTH_TOKEN_INFO + err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo) + if err != nil { + t.Fatalf("Failed to set environment variable: %v", err) + } + }, + want: nil, + wantErr: true, + }, + { + name: "This UT tests if _token_refresh_source fails to parse due to value out of uint8 range", + uotm: &UserOAuthTokenManager{}, + args: args{ + ctx: context.Background(), + }, + setup: func(t *testing.T) { + tokenInfo := formatTokenInfo(847) // Set the environment variable AZCOPY_OAUTH_TOKEN_INFO - err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfoJSON) + err := os.Setenv("AZCOPY_OAUTH_TOKEN_INFO", tokenInfo) if err != nil { t.Fatalf("Failed to set environment variable: %v", err) }