diff --git a/.kokoro/conformance-tests.sh b/.kokoro/conformance-tests.sh new file mode 100755 index 000000000..9c90d3586 --- /dev/null +++ b/.kokoro/conformance-tests.sh @@ -0,0 +1,70 @@ +#!/bin/bash + +set -euo pipefail + +# Docker image to pull (your test "server" image) +readonly TEST_IMAGE="gcr.io/client-debugging/conformance_test_environment_0:conformance_test_environment_v2" + +# Project root +readonly PROJECT_ROOT="$(git rev-parse --show-toplevel)" + +# Test directory at the project root +readonly TEST_DIR="conformance-tests" + +# Check if the test directory exists +if [[ ! -d "${PROJECT_ROOT}/${TEST_DIR}" ]]; then + echo "ERROR: Test directory '${TEST_DIR}' not found. Aborting." >&2 + exit 1 +fi + +docker pull "${TEST_IMAGE}" || { # Pull the docker image. Exit if it fails. + echo "ERROR: Failed to pull Docker image. Aborting." >&2 + exit 1 +} + + +# Start the Docker container (detached mode, expose port) +PORT=5007 # Set the desired port here +container_id=$(docker run -d -p "${PORT}":5000 "${TEST_IMAGE}") || { + echo "ERROR: Failed to start Docker container. Aborting." >&2 + exit 1 +} + +cleanup() { # Define the cleanup function + docker stop "${container_id}" || true # Stop; ignore errors if already stopped + docker rm "${container_id}" || true # Remove; ignore errors if already removed +} + +trap cleanup EXIT # Ensure cleanup on ANY exit (normal or error) + +# Wait for the container's port to be open (adjust timeout as needed) +for i in {1..30}; do # Try for 30 seconds + if docker exec "${container_id}" bash -c 'nc -z localhost 5000'; then + echo "Container port 5000 is open. Proceeding with tests..." + break # Port is open, exit the loop + fi + sleep 1 +done + + +if [[ $i -eq 30 ]]; then # timeout reached + echo "ERROR: Timeout waiting for container port 5000 to open. Aborting." >&2 + docker stop "${container_id}" # Stop the container on error + docker rm "${container_id}" + exit 1 +fi + + +# Run your tests (outside the container, against localhost:5000) +python3 -m pip install --user pytest # Install pytest if needed +cd "${PROJECT_ROOT}/${TEST_DIR}" +PORT="${PORT}" python3 -m pytest user_tests.py # Or any other test runner + +# Capture the exit code of the test run +exit_code=$? + +# Stop and remove the container +docker stop "${container_id}" +docker rm "${container_id}" + +exit "${exit_code}" diff --git a/conformance-tests/data/authorized_user_200.json b/conformance-tests/data/authorized_user_200.json new file mode 100644 index 000000000..910e0acf7 --- /dev/null +++ b/conformance-tests/data/authorized_user_200.json @@ -0,0 +1,9 @@ +{ + "client_id": "conformance_client", + "client_secret": "conformance_client_secret", + "refresh_token": "mock_refresh_token", + "token_uri": "http://localhost:5000/oauth2/token200", + "scopes": ["email", "profile"] +} + + \ No newline at end of file diff --git a/conformance-tests/user_tests.py b/conformance-tests/user_tests.py new file mode 100644 index 000000000..90619ac5b --- /dev/null +++ b/conformance-tests/user_tests.py @@ -0,0 +1,38 @@ +import pytest +from google.auth.transport.requests import Request +import os +import requests +from google.oauth2 import credentials + +DATA_DIR = os.path.join(os.path.dirname(__file__), "data") + +def test_valid_token_refresh(): + port = os.environ.get("PORT", "5000") # Get port from environment, default to 5000 + url = f"http://localhost:{port}/oauth2/token200" + + # Create a Credentials object (replace with your actual refresh token) + creds = credentials.Credentials( + token=None, # No initial token + refresh_token='mock_refresh_token', # Your refresh token + token_uri=url, # Token endpoint + client_id='conformance_client', # Your client ID + client_secret='conformance_client_secret', # Your client secret + scopes=['email', 'profile'], # Your scopes, if needed (might not be for refresh) + ) + + # json_file_path = os.path.join(DATA_DIR, "authorized_user_200.json") + # creds = credentials.Credentials.from_authorized_user_file(json_file_path) + + # Refresh the credentials to get a new access token + try: + creds.refresh(Request()) # Refresh the token + except Exception as e: + pytest.fail(f"Token refresh failed: {e}") + + headers = {} + creds.apply(headers) + + url = f"http://localhost:{port}/oauth2/validate" # Make sure your server is running on this address and port + response = requests.post(url, headers=headers) + + assert response.status_code == 200 \ No newline at end of file diff --git a/google/oauth2/credentials.py b/google/oauth2/credentials.py index 6e158089f..7cebf1832 100644 --- a/google/oauth2/credentials.py +++ b/google/oauth2/credentials.py @@ -484,7 +484,7 @@ def from_authorized_user_info(cls, info, scopes=None): return cls( token=info.get("token"), refresh_token=info.get("refresh_token"), - token_uri=_GOOGLE_OAUTH2_TOKEN_ENDPOINT, # always overrides + token_uri=info.get("token_uri"), # always overrides scopes=scopes, client_id=info.get("client_id"), client_secret=info.get("client_secret"),