Skip to main content
Glama

MCPJungle mcp gateway

by mcpjungle
Mozilla Public License 2.0
638
  • Apple
util_test.go•5.71 kB
package internal import ( "encoding/base64" "strings" "testing" ) func TestGenerateAccessToken(t *testing.T) { t.Run("successful token generation", func(t *testing.T) { token, err := GenerateAccessToken() if err != nil { t.Fatalf("Expected no error, got: %v", err) } if token == "" { t.Fatal("Expected non-empty token") } }) t.Run("token length validation", func(t *testing.T) { token, err := GenerateAccessToken() if err != nil { t.Fatalf("Expected no error, got: %v", err) } // Decode the base64 URL token to check actual byte length decoded, err := base64.URLEncoding.WithPadding(base64.NoPadding).DecodeString(token) if err != nil { t.Fatalf("Expected valid base64 URL encoding, got error: %v", err) } expectedLength := 32 // 256 bits = 32 bytes if len(decoded) != expectedLength { t.Errorf("Expected decoded token length %d, got %d", expectedLength, len(decoded)) } }) t.Run("token uniqueness", func(t *testing.T) { // Generate multiple tokens and ensure they're unique tokens := make(map[string]bool) const numTokens = 100 for i := 0; i < numTokens; i++ { token, err := GenerateAccessToken() if err != nil { t.Fatalf("Expected no error on token %d, got: %v", i, err) } if tokens[token] { t.Errorf("Duplicate token generated: %s", token) } tokens[token] = true } if len(tokens) != numTokens { t.Errorf("Expected %d unique tokens, got %d", numTokens, len(tokens)) } }) t.Run("token format validation", func(t *testing.T) { token, err := GenerateAccessToken() if err != nil { t.Fatalf("Expected no error, got: %v", err) } // Check that token only contains valid base64 URL characters validChars := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_" for _, char := range token { if !strings.ContainsRune(validChars, char) { t.Errorf("Token contains invalid character: %c", char) } } // Verify no padding characters (since we use NoPadding) if strings.Contains(token, "=") { t.Error("Token contains padding characters, expected none") } }) t.Run("token entropy validation", func(t *testing.T) { // Generate multiple tokens and check for reasonable entropy tokens := make([]string, 50) for i := 0; i < 50; i++ { token, err := GenerateAccessToken() if err != nil { t.Fatalf("Expected no error on token %d, got: %v", i, err) } tokens[i] = token } // Check that tokens are reasonably different from each other // This is a basic check - in practice, crypto/rand should provide good entropy similarityCount := 0 for i := 0; i < len(tokens); i++ { for j := i + 1; j < len(tokens); j++ { if tokens[i] == tokens[j] { similarityCount++ } } } if similarityCount > 0 { t.Errorf("Found %d duplicate tokens, expected 0", similarityCount) } }) } func TestGenerateAccessToken_ErrorHandling(t *testing.T) { // Note: It's difficult to test the actual error case of crypto/rand.Read failing // in a normal environment, but we can document the expected behavior t.Run("function signature validation", func(t *testing.T) { // Verify the function signature matches expectations // GenerateAccessToken is a function that should always be callable _ = GenerateAccessToken }) t.Run("return type validation", func(t *testing.T) { token, err := GenerateAccessToken() // Both return values should be of correct types // token is already a string, so we just check it's not empty if token == "" { t.Error("First return value is empty string") } // err is already an error interface, so we just check it's nil if err != nil { t.Error("Expected no error, got error") } }) } func TestGenerateAccessToken_EdgeCases(t *testing.T) { t.Run("multiple rapid calls", func(t *testing.T) { // Test that rapid successive calls work correctly const numRapidCalls = 1000 tokens := make([]string, numRapidCalls) errors := make([]error, numRapidCalls) for i := 0; i < numRapidCalls; i++ { tokens[i], errors[i] = GenerateAccessToken() } // Check for any errors for i, err := range errors { if err != nil { t.Errorf("Error on rapid call %d: %v", i, err) } } // Check for any empty tokens for i, token := range tokens { if token == "" { t.Errorf("Empty token on rapid call %d", i) } } // Check for uniqueness tokenSet := make(map[string]bool) for _, token := range tokens { if tokenSet[token] { t.Errorf("Duplicate token found in rapid calls: %s", token) } tokenSet[token] = true } }) t.Run("concurrent token generation", func(t *testing.T) { // Test that concurrent calls work correctly const numConcurrent = 100 tokenChan := make(chan string, numConcurrent) errorChan := make(chan error, numConcurrent) // Launch concurrent goroutines for i := 0; i < numConcurrent; i++ { go func() { token, err := GenerateAccessToken() tokenChan <- token errorChan <- err }() } // Collect results tokens := make([]string, numConcurrent) errors := make([]error, numConcurrent) for i := 0; i < numConcurrent; i++ { tokens[i] = <-tokenChan errors[i] = <-errorChan } // Check for any errors for i, err := range errors { if err != nil { t.Errorf("Error on concurrent call %d: %v", i, err) } } // Check for any empty tokens for i, token := range tokens { if token == "" { t.Errorf("Empty token on concurrent call %d", i) } } // Check for uniqueness tokenSet := make(map[string]bool) for _, token := range tokens { if tokenSet[token] { t.Errorf("Duplicate token found in concurrent calls: %s", token) } tokenSet[token] = true } }) }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mcpjungle/MCPJungle'

If you have feedback or need assistance with the MCP directory API, please join our Discord server