Skip to content

Commit

Permalink
pushed changes along with testcases. Tested all the flows
Browse files Browse the repository at this point in the history
  • Loading branch information
Parag.jain committed Oct 7, 2024
1 parent acf6623 commit 835fea2
Show file tree
Hide file tree
Showing 2 changed files with 342 additions and 9 deletions.
23 changes: 14 additions & 9 deletions cmd/suseconnect/suseconnect.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,7 @@ func main() {
connect.CFG.Namespace = namespace
writeConfig = true
}
if token != "" {
connect.CFG.Token = token
processedToken, processTokenErr := processToken(token)
if processTokenErr != nil {
util.Debug.Printf("Error Processing token %+v", processTokenErr)
os.Exit(1)
}
connect.CFG.Token = processedToken
}
parseRegistrationToken(token)
if product.isSet {
if p, err := connect.SplitTriplet(product.value); err != nil {
fmt.Print("Please provide the product identifier in this format: ")
Expand Down Expand Up @@ -310,6 +302,18 @@ func main() {
}
}

func parseRegistrationToken(token string) {
if token != "" {
connect.CFG.Token = token
processedToken, processTokenErr := processToken(token)
if processTokenErr != nil {
fmt.Printf("Error Processing token %+v", processTokenErr)
os.Exit(1)
}
connect.CFG.Token = processedToken
}
}

func maybeBrokenSMTError() error {
if !connect.URLDefault() && !connect.UpToDate() {
return fmt.Errorf("Your Registration Proxy server doesn't support this function. " +
Expand Down Expand Up @@ -425,6 +429,7 @@ func readTokenFromReader(reader io.Reader) (string, error) {
return "", fmt.Errorf("failed to read token from reader: %w", err)
}
token := strings.TrimSuffix(tokenBytes, "\n")
token = strings.TrimSpace(token)
if token == "" {
return "", fmt.Errorf("error: token cannot be empty after reading")
}
Expand Down
328 changes: 328 additions & 0 deletions cmd/suseconnect/suseconnect_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
package main

import (
"errors"
"fmt"
"github.com/SUSE/connect-ng/internal/connect"
"github.com/SUSE/connect-ng/internal/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"os"
"strings"
"testing"
)

var processTokenFunc = processToken

var exitCalled bool
var exit = func(code int) {
exitCalled = true
}

// Mock for processToken function in the test file.
type MockProcessToken struct {
mock.Mock
}

func (m *MockProcessToken) ProcessToken(token string) (string, error) {
args := m.Called(token)
return args.String(0), args.Error(1)
}

func init() {
processTokenFunc = processToken
}

type errorReader struct{}

func (e *errorReader) Read(p []byte) (n int, err error) {
return 0, fmt.Errorf("forced reader error")
}

func TestReadTokenFromErrorValidToken(t *testing.T) {
inputToken := "validToken\n"
reader := strings.NewReader(inputToken)
token, err := readTokenFromReader(reader)
if err != nil {
t.Fatalf("Expected no error but got %v", err)
}
if token != "validToken" {
t.Fatalf("Expected token string to be 'validToken' but got '%s'", token)
}
}

func TestReadTokenFromReader_MultipleNewlines(t *testing.T) {
input := "firstToken\nsecondToken\n"
reader := strings.NewReader(input)

token, err := readTokenFromReader(reader)
if err != nil {
t.Fatalf("Expected no error, but got %v", err)
}

expected := "firstToken"
if token != expected {
t.Errorf("Expected token to be '%s', but got '%s'", expected, token)
}
}

func TestReadTokenFromReader_EmptyInput(t *testing.T) {
reader := strings.NewReader("")

token, err := readTokenFromReader(reader)
if err == nil {
t.Fatalf("Expected error, but got none")
}

expectedError := "error: token cannot be empty after reading"
if err.Error() != expectedError {
t.Errorf("Expected error '%s', but got '%s'", expectedError, err.Error())
}

if token != "" {
t.Errorf("Expected empty token, but got '%s'", token)
}
}

func TestReadTokenFromReader_OnlyNewline(t *testing.T) {
reader := strings.NewReader("\n") // Input contains only a newline

token, err := readTokenFromReader(reader)
if err == nil {
t.Fatalf("Expected error, but got none")
}

expectedError := "error: token cannot be empty after reading"
if err.Error() != expectedError {
t.Errorf("Expected error '%s', but got '%s'", expectedError, err.Error())
}

if token != "" {
t.Errorf("Expected empty token, but got '%s'", token)
}
}

func TestReadTokenFromReader_ErrorProducingReader(t *testing.T) {
reader := &errorReader{} // Custom reader that always returns an error

token, err := readTokenFromReader(reader)
if err == nil {
t.Fatalf("Expected error, but got none")
}

expectedError := "failed to read token from reader: forced reader error"
if err.Error() != expectedError {
t.Errorf("Expected error '%s', but got '%s'", expectedError, err.Error())
}

if token != "" {
t.Errorf("Expected empty token, but got '%s'", token)
}
}
func TestReadTokenFromReader_OnlyWhitespace(t *testing.T) {
reader := strings.NewReader(" \n") // Input contains only spaces and newline

token, err := readTokenFromReader(reader)
if err == nil {
t.Fatalf("Expected error, but got none")
}

expectedError := "error: token cannot be empty after reading"
if err.Error() != expectedError {
t.Errorf("Expected error '%s', but got '%s'", expectedError, err.Error())
}

if token != "" {
t.Errorf("Expected empty token, but got '%s'", token)
}
}

func TestProcessToken_RegularToken(t *testing.T) {
token := "myRegularToken"
result, err := processToken(token)
if err != nil {
t.Fatalf("Expected no error, but got %v", err)
}

if result != token {
t.Errorf("Expected token to be '%s', but got '%s'", token, result)
}
}

func TestProcessToken_TokenFromFile(t *testing.T) {
tmpFile, err := os.CreateTemp("", "tokenfile")
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
defer os.Remove(tmpFile.Name()) // Clean up the temp file

expectedToken := "fileToken\n"
if _, err := tmpFile.WriteString(expectedToken); err != nil {
t.Fatalf("Failed to write to temp file: %v", err)
}
tmpFile.Close()

token := "@" + tmpFile.Name()
result, err := processToken(token)
if err != nil {
t.Fatalf("Expected no error, but got %v", err)
}

expectedToken = strings.TrimSpace(expectedToken)
if result != expectedToken {
t.Errorf("Expected token to be '%s', but got '%s'", expectedToken, result)
}
}

func TestProcessToken_NonExistentFile(t *testing.T) {
token := "@/non/existent/file"
_, err := processToken(token)
if err == nil {
t.Fatalf("Expected error for non-existent file, but got none")
}

expectedError := "failed to open token file '/non/existent/file'"
if !strings.Contains(err.Error(), expectedError) {
t.Errorf("Expected error containing '%s', but got '%v'", expectedError, err)
}
}

func TestProcessToken_TokenFromStdin(t *testing.T) {
// Create a temporary file to simulate stdin
tempFile, err := os.CreateTemp("", "test_stdin")
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
defer os.Remove(tempFile.Name()) // Clean up the temp file

// Write the test token to the temporary file
expectedToken := "stdinToken\n"
if _, err := tempFile.WriteString(expectedToken); err != nil {
t.Fatalf("Failed to write to temp file: %v", err)
}

// Close the file so we can reopen it as stdin
tempFile.Close()

// Temporarily replace os.Stdin with the temp file
oldStdin := os.Stdin
defer func() { os.Stdin = oldStdin }() // Restore original stdin
file, err := os.Open(tempFile.Name()) // Reopen the temp file for reading
if err != nil {
t.Fatalf("Failed to open temp file: %v", err)
}
os.Stdin = file // Set os.Stdin to the temp file

// Call processToken with "-"
result, err := processToken("-")
if err != nil {
t.Fatalf("Expected no error, but got %v", err)
}

// Verify the result
expectedToken = strings.TrimSpace(expectedToken) // Trim newline
if result != expectedToken {
t.Errorf("Expected token to be '%s', but got '%s'", expectedToken, result)
}
}

func TestProcessToken_ErrorReadingStdin(t *testing.T) {
// Create a temporary file to simulate stdin
tempFile, err := os.CreateTemp("", "test_stdin_empty")
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
defer os.Remove(tempFile.Name()) // Clean up the temp file

// Close the temp file to simulate EOF
tempFile.Close()

// Temporarily replace os.Stdin with the temp file
oldStdin := os.Stdin
defer func() { os.Stdin = oldStdin }() // Restore original stdin
file, err := os.Open(tempFile.Name()) // Open the temp file for reading
if err != nil {
t.Fatalf("Failed to open temp file: %v", err)
}
os.Stdin = file // Set os.Stdin to the temp file

// Call processToken with "-"
_, err = processToken("-")
if err == nil {
t.Fatalf("Expected error reading from stdin, but got none")
}

// Check for the specific error about an empty token
expectedError := "error: token cannot be empty after reading"
if !strings.Contains(err.Error(), expectedError) {
t.Errorf("Expected error containing '%s', but got '%v'", expectedError, err)
}
}

func parseRegistrationTokenWithInjection(token string) {
if token != "" {
connect.CFG.Token = token
processedToken, processTokenErr := processTokenFunc(token)
if processTokenErr != nil {
util.Debug.Printf("Error Processing token %+v", processTokenErr)
exit(1) // Use the mockable exit function
}
connect.CFG.Token = processedToken
}
}

func TestParseToken_Success(t *testing.T) {
// Mocking processToken using testify's mock package
mockProcessToken := new(MockProcessToken)
mockProcessToken.On("ProcessToken", "valid-token").Return("processed-token", nil)

// Override processTokenFunc to use the mocked function
processTokenFunc = mockProcessToken.ProcessToken

// Reset exitCalled to false for the new test
exitCalled = false

// Call the function with a valid token
parseRegistrationTokenWithInjection("valid-token")

// Assertions
assert.Equal(t, "processed-token", connect.CFG.Token, "Token should be processed correctly")
assert.False(t, exitCalled, "os.Exit (simulated) should not be called in a successful case")

// Verify the mock expectations
mockProcessToken.AssertExpectations(t)
}

func TestParseToken_ProcessTokenError(t *testing.T) {
// Mocking processToken to return an error
mockProcessToken := new(MockProcessToken)
mockProcessToken.On("ProcessToken", "invalid-token").Return("", errors.New("failed to process token"))

// Override processTokenFunc to use the mocked function
processTokenFunc = mockProcessToken.ProcessToken

// Reset exitCalled to false for the new test
exitCalled = false

// Call the function with an invalid token
parseRegistrationTokenWithInjection("invalid-token")

// Assertions
assert.True(t, exitCalled, "os.Exit (simulated) should be called when processToken fails")
assert.Equal(t, "", connect.CFG.Token, "Token should not be updated when processToken fails")

// Verify the mock expectations
mockProcessToken.AssertExpectations(t)
}

func TestParseToken_EmptyToken(t *testing.T) {
// Reset exitCalled to false for the new test
exitCalled = false

// Call the function with an empty token
parseRegistrationTokenWithInjection("")

// Assertions
assert.Empty(t, connect.CFG.Token, "Token should not be updated when input token is empty")
assert.False(t, exitCalled, "os.Exit (simulated) should not be called for empty token")
}

0 comments on commit 835fea2

Please sign in to comment.