| 
 | 1 | +package mcpreportportal  | 
 | 2 | + | 
 | 3 | +import (  | 
 | 4 | +	"context"  | 
 | 5 | +	"net/http"  | 
 | 6 | +	"net/http/httptest"  | 
 | 7 | +	"testing"  | 
 | 8 | + | 
 | 9 | +	"github.com/stretchr/testify/assert"  | 
 | 10 | +)  | 
 | 11 | + | 
 | 12 | +func TestExtractRPProjectFromRequest(t *testing.T) {  | 
 | 13 | +	tests := []struct {  | 
 | 14 | +		name           string  | 
 | 15 | +		headers        map[string]string  | 
 | 16 | +		expectedResult string  | 
 | 17 | +	}{  | 
 | 18 | +		{  | 
 | 19 | +			name:           "valid X-Project header",  | 
 | 20 | +			headers:        map[string]string{"X-Project": "test-project"},  | 
 | 21 | +			expectedResult: "test-project",  | 
 | 22 | +		},  | 
 | 23 | +		{  | 
 | 24 | +			name:           "X-Project header with whitespace",  | 
 | 25 | +			headers:        map[string]string{"X-Project": "  test-project  "},  | 
 | 26 | +			expectedResult: "test-project",  | 
 | 27 | +		},  | 
 | 28 | +		{  | 
 | 29 | +			name:           "empty X-Project header",  | 
 | 30 | +			headers:        map[string]string{"X-Project": ""},  | 
 | 31 | +			expectedResult: "",  | 
 | 32 | +		},  | 
 | 33 | +		{  | 
 | 34 | +			name:           "missing X-Project header",  | 
 | 35 | +			headers:        map[string]string{},  | 
 | 36 | +			expectedResult: "",  | 
 | 37 | +		},  | 
 | 38 | +		{  | 
 | 39 | +			name:           "X-Project header with only whitespace",  | 
 | 40 | +			headers:        map[string]string{"X-Project": "   "},  | 
 | 41 | +			expectedResult: "",  | 
 | 42 | +		},  | 
 | 43 | +		{  | 
 | 44 | +			name:           "case insensitive header name",  | 
 | 45 | +			headers:        map[string]string{"x-project": "test-project"},  | 
 | 46 | +			expectedResult: "test-project",  | 
 | 47 | +		},  | 
 | 48 | +		{  | 
 | 49 | +			name: "other headers present but no X-Project",  | 
 | 50 | +			headers: map[string]string{  | 
 | 51 | +				"Authorization": "Bearer token",  | 
 | 52 | +				"Content-Type":  "application/json",  | 
 | 53 | +			},  | 
 | 54 | +			expectedResult: "",  | 
 | 55 | +		},  | 
 | 56 | +	}  | 
 | 57 | + | 
 | 58 | +	for _, tt := range tests {  | 
 | 59 | +		t.Run(tt.name, func(t *testing.T) {  | 
 | 60 | +			req := httptest.NewRequest("GET", "/test", nil)  | 
 | 61 | + | 
 | 62 | +			// Set headers  | 
 | 63 | +			for key, value := range tt.headers {  | 
 | 64 | +				req.Header.Set(key, value)  | 
 | 65 | +			}  | 
 | 66 | + | 
 | 67 | +			result := extractRPProjectFromRequest(req)  | 
 | 68 | +			assert.Equal(t, tt.expectedResult, result)  | 
 | 69 | +		})  | 
 | 70 | +	}  | 
 | 71 | +}  | 
 | 72 | + | 
 | 73 | +func TestWithProjectInContext(t *testing.T) {  | 
 | 74 | +	ctx := context.Background()  | 
 | 75 | +	project := "test-project"  | 
 | 76 | + | 
 | 77 | +	// Test adding project to context  | 
 | 78 | +	ctxWithProject := WithProjectInContext(ctx, project)  | 
 | 79 | + | 
 | 80 | +	// Test retrieving project from context  | 
 | 81 | +	retrievedProject, ok := GetProjectFromContext(ctxWithProject)  | 
 | 82 | +	assert.True(t, ok)  | 
 | 83 | +	assert.Equal(t, project, retrievedProject)  | 
 | 84 | + | 
 | 85 | +	// Test that original context doesn't have project  | 
 | 86 | +	_, ok = GetProjectFromContext(ctx)  | 
 | 87 | +	assert.False(t, ok)  | 
 | 88 | +}  | 
 | 89 | + | 
 | 90 | +func TestGetProjectFromContext(t *testing.T) {  | 
 | 91 | +	tests := []struct {  | 
 | 92 | +		name            string  | 
 | 93 | +		contextValue    interface{}  | 
 | 94 | +		expectedProject string  | 
 | 95 | +		expectedOk      bool  | 
 | 96 | +	}{  | 
 | 97 | +		{  | 
 | 98 | +			name:            "valid project string",  | 
 | 99 | +			contextValue:    "test-project",  | 
 | 100 | +			expectedProject: "test-project",  | 
 | 101 | +			expectedOk:      true,  | 
 | 102 | +		},  | 
 | 103 | +		{  | 
 | 104 | +			name:            "empty project string",  | 
 | 105 | +			contextValue:    "",  | 
 | 106 | +			expectedProject: "",  | 
 | 107 | +			expectedOk:      false,  | 
 | 108 | +		},  | 
 | 109 | +		{  | 
 | 110 | +			name:            "nil context value",  | 
 | 111 | +			contextValue:    nil,  | 
 | 112 | +			expectedProject: "",  | 
 | 113 | +			expectedOk:      false,  | 
 | 114 | +		},  | 
 | 115 | +		{  | 
 | 116 | +			name:            "non-string context value",  | 
 | 117 | +			contextValue:    123,  | 
 | 118 | +			expectedProject: "",  | 
 | 119 | +			expectedOk:      false,  | 
 | 120 | +		},  | 
 | 121 | +		{  | 
 | 122 | +			name:            "context without project key",  | 
 | 123 | +			contextValue:    nil, // This will be handled by the context not having the key  | 
 | 124 | +			expectedProject: "",  | 
 | 125 | +			expectedOk:      false,  | 
 | 126 | +		},  | 
 | 127 | +	}  | 
 | 128 | + | 
 | 129 | +	for _, tt := range tests {  | 
 | 130 | +		t.Run(tt.name, func(t *testing.T) {  | 
 | 131 | +			ctx := context.Background()  | 
 | 132 | + | 
 | 133 | +			if tt.contextValue != nil {  | 
 | 134 | +				ctx = context.WithValue(ctx, RPProjectContextKey, tt.contextValue)  | 
 | 135 | +			}  | 
 | 136 | + | 
 | 137 | +			project, ok := GetProjectFromContext(ctx)  | 
 | 138 | +			assert.Equal(t, tt.expectedOk, ok)  | 
 | 139 | +			assert.Equal(t, tt.expectedProject, project)  | 
 | 140 | +		})  | 
 | 141 | +	}  | 
 | 142 | +}  | 
 | 143 | + | 
 | 144 | +func TestHTTPTokenMiddleware_ProjectExtraction(t *testing.T) {  | 
 | 145 | +	tests := []struct {  | 
 | 146 | +		name            string  | 
 | 147 | +		headers         map[string]string  | 
 | 148 | +		expectProject   bool  | 
 | 149 | +		expectedProject string  | 
 | 150 | +	}{  | 
 | 151 | +		{  | 
 | 152 | +			name:            "X-Project header present",  | 
 | 153 | +			headers:         map[string]string{"X-Project": "test-project"},  | 
 | 154 | +			expectProject:   true,  | 
 | 155 | +			expectedProject: "test-project",  | 
 | 156 | +		},  | 
 | 157 | +		{  | 
 | 158 | +			name:            "X-Project header missing",  | 
 | 159 | +			headers:         map[string]string{},  | 
 | 160 | +			expectProject:   false,  | 
 | 161 | +			expectedProject: "",  | 
 | 162 | +		},  | 
 | 163 | +		{  | 
 | 164 | +			name:            "X-Project header empty",  | 
 | 165 | +			headers:         map[string]string{"X-Project": ""},  | 
 | 166 | +			expectProject:   false,  | 
 | 167 | +			expectedProject: "",  | 
 | 168 | +		},  | 
 | 169 | +		{  | 
 | 170 | +			name:            "X-Project header with whitespace",  | 
 | 171 | +			headers:         map[string]string{"X-Project": "  test-project  "},  | 
 | 172 | +			expectProject:   true,  | 
 | 173 | +			expectedProject: "test-project",  | 
 | 174 | +		},  | 
 | 175 | +	}  | 
 | 176 | + | 
 | 177 | +	for _, tt := range tests {  | 
 | 178 | +		t.Run(tt.name, func(t *testing.T) {  | 
 | 179 | +			// Create a test handler that checks the context  | 
 | 180 | +			var capturedProject string  | 
 | 181 | +			var projectFound bool  | 
 | 182 | + | 
 | 183 | +			testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {  | 
 | 184 | +				project, ok := GetProjectFromContext(r.Context())  | 
 | 185 | +				capturedProject = project  | 
 | 186 | +				projectFound = ok  | 
 | 187 | +				w.WriteHeader(http.StatusOK)  | 
 | 188 | +			})  | 
 | 189 | + | 
 | 190 | +			// Create middleware  | 
 | 191 | +			middleware := HTTPTokenMiddleware(testHandler)  | 
 | 192 | + | 
 | 193 | +			// Create request with headers  | 
 | 194 | +			req := httptest.NewRequest("GET", "/test", nil)  | 
 | 195 | +			for key, value := range tt.headers {  | 
 | 196 | +				req.Header.Set(key, value)  | 
 | 197 | +			}  | 
 | 198 | + | 
 | 199 | +			// Create response recorder  | 
 | 200 | +			rr := httptest.NewRecorder()  | 
 | 201 | + | 
 | 202 | +			// Execute middleware  | 
 | 203 | +			middleware.ServeHTTP(rr, req)  | 
 | 204 | + | 
 | 205 | +			// Verify response  | 
 | 206 | +			assert.Equal(t, http.StatusOK, rr.Code)  | 
 | 207 | + | 
 | 208 | +			// Verify project extraction  | 
 | 209 | +			assert.Equal(t, tt.expectProject, projectFound)  | 
 | 210 | +			if tt.expectProject {  | 
 | 211 | +				assert.Equal(t, tt.expectedProject, capturedProject)  | 
 | 212 | +			}  | 
 | 213 | +		})  | 
 | 214 | +	}  | 
 | 215 | +}  | 
 | 216 | + | 
 | 217 | +func TestHTTPTokenMiddleware_CombinedTokenAndProject(t *testing.T) {  | 
 | 218 | +	// Test that both token and project can be extracted simultaneously  | 
 | 219 | +	req := httptest.NewRequest("GET", "/test", nil)  | 
 | 220 | +	req.Header.Set("Authorization", "Bearer 1234567890123456")  | 
 | 221 | +	req.Header.Set("X-Project", "test-project")  | 
 | 222 | + | 
 | 223 | +	var capturedToken, capturedProject string  | 
 | 224 | +	var tokenFound, projectFound bool  | 
 | 225 | + | 
 | 226 | +	testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {  | 
 | 227 | +		token, ok := GetTokenFromContext(r.Context())  | 
 | 228 | +		capturedToken = token  | 
 | 229 | +		tokenFound = ok  | 
 | 230 | + | 
 | 231 | +		project, ok := GetProjectFromContext(r.Context())  | 
 | 232 | +		capturedProject = project  | 
 | 233 | +		projectFound = ok  | 
 | 234 | + | 
 | 235 | +		w.WriteHeader(http.StatusOK)  | 
 | 236 | +	})  | 
 | 237 | + | 
 | 238 | +	middleware := HTTPTokenMiddleware(testHandler)  | 
 | 239 | +	rr := httptest.NewRecorder()  | 
 | 240 | + | 
 | 241 | +	middleware.ServeHTTP(rr, req)  | 
 | 242 | + | 
 | 243 | +	// Verify both token and project were extracted  | 
 | 244 | +	assert.Equal(t, http.StatusOK, rr.Code)  | 
 | 245 | +	assert.True(t, tokenFound)  | 
 | 246 | +	assert.Equal(t, "1234567890123456", capturedToken)  | 
 | 247 | +	assert.True(t, projectFound)  | 
 | 248 | +	assert.Equal(t, "test-project", capturedProject)  | 
 | 249 | +}  | 
 | 250 | + | 
 | 251 | +func TestHTTPTokenMiddleware_NoHeaders(t *testing.T) {  | 
 | 252 | +	// Test middleware with no headers  | 
 | 253 | +	req := httptest.NewRequest("GET", "/test", nil)  | 
 | 254 | + | 
 | 255 | +	var tokenFound, projectFound bool  | 
 | 256 | + | 
 | 257 | +	testHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {  | 
 | 258 | +		_, tokenFound = GetTokenFromContext(r.Context())  | 
 | 259 | +		_, projectFound = GetProjectFromContext(r.Context())  | 
 | 260 | +		w.WriteHeader(http.StatusOK)  | 
 | 261 | +	})  | 
 | 262 | + | 
 | 263 | +	middleware := HTTPTokenMiddleware(testHandler)  | 
 | 264 | +	rr := httptest.NewRecorder()  | 
 | 265 | + | 
 | 266 | +	middleware.ServeHTTP(rr, req)  | 
 | 267 | + | 
 | 268 | +	// Verify no token or project were found  | 
 | 269 | +	assert.Equal(t, http.StatusOK, rr.Code)  | 
 | 270 | +	assert.False(t, tokenFound)  | 
 | 271 | +	assert.False(t, projectFound)  | 
 | 272 | +}  | 
0 commit comments