mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-08-09 00:16:57 -07:00
100 lines
3.8 KiB
Python
100 lines
3.8 KiB
Python
# Copyright 2026 Google LLC
|
|
# Apache-2.0 License
|
|
|
|
"""Unit tests for workflow/config.py."""
|
|
|
|
import json
|
|
import os
|
|
import pytest
|
|
|
|
from config import Config, ConfigurationError
|
|
|
|
|
|
def test_config_defaults(monkeypatch):
|
|
"""Tests default configuration fallback values when environment variables are unset."""
|
|
monkeypatch.delenv("REPO_URL", raising=False)
|
|
monkeypatch.delenv("GOOGLE_CLOUD_PROJECT", raising=False)
|
|
monkeypatch.delenv("GOOGLE_CLOUD_LOCATION", raising=False)
|
|
monkeypatch.delenv("MODEL_NAME", raising=False)
|
|
monkeypatch.delenv("MAX_ATTEMPTS", raising=False)
|
|
|
|
cfg = Config()
|
|
assert cfg.repo_url == "https://github.com/joneba-google/gemini-cli-clone"
|
|
assert cfg.project_id == "gcli-intern-project-2026"
|
|
assert cfg.location == "global"
|
|
assert cfg.model_name == "gemini-3.5-flash"
|
|
assert cfg.max_attempts == 5
|
|
assert cfg.repo_name == "gemini-cli-clone"
|
|
|
|
|
|
def test_config_max_attempts_valid(monkeypatch):
|
|
"""Tests custom MAX_ATTEMPTS environment variable parsing."""
|
|
monkeypatch.setenv("MAX_ATTEMPTS", "12")
|
|
cfg = Config()
|
|
assert cfg.max_attempts == 12
|
|
|
|
|
|
def test_config_max_attempts_invalid_string(monkeypatch):
|
|
"""Tests that invalid MAX_ATTEMPTS strings fall back cleanly to 5."""
|
|
monkeypatch.setenv("MAX_ATTEMPTS", "invalid_string")
|
|
cfg = Config()
|
|
assert cfg.max_attempts == 5
|
|
|
|
|
|
def test_config_max_attempts_zero_or_negative(monkeypatch):
|
|
"""Tests lower bound enforcement (max(val, 1)) for zero or negative values."""
|
|
monkeypatch.setenv("MAX_ATTEMPTS", "0")
|
|
cfg1 = Config()
|
|
assert cfg1.max_attempts == 1
|
|
|
|
monkeypatch.setenv("MAX_ATTEMPTS", "-5")
|
|
cfg2 = Config()
|
|
assert cfg2.max_attempts == 1
|
|
|
|
|
|
def test_config_repo_name_derivation(monkeypatch):
|
|
"""Tests repository name parsing from REPO_URL with trailing slashes and .git suffixes."""
|
|
monkeypatch.setenv("REPO_URL", "https://github.com/my-org/my-custom-repo.git/")
|
|
cfg = Config()
|
|
assert cfg.repo_name == "my-custom-repo"
|
|
assert cfg.pr_repo_path == os.path.join("/tmp/pr", "my-custom-repo")
|
|
assert cfg.eval_repo_path == os.path.join("/tmp/eval", "my-custom-repo")
|
|
|
|
|
|
def test_load_and_validate_firestore_doc_valid(monkeypatch):
|
|
"""Tests loading and validating a valid JSON FIRESTORE_DOC string."""
|
|
valid_doc = {"workable_spec": {"issue_id": "190"}, "status": "PENDING"}
|
|
monkeypatch.setenv("FIRESTORE_DOC", json.dumps(valid_doc))
|
|
|
|
cfg = Config()
|
|
parsed = cfg.load_and_validate_firestore_doc()
|
|
assert parsed["workable_spec"]["issue_id"] == "190"
|
|
assert parsed["status"] == "PENDING"
|
|
|
|
|
|
def test_load_and_validate_firestore_doc_missing(monkeypatch):
|
|
"""Tests error handling when FIRESTORE_DOC environment variable is missing."""
|
|
monkeypatch.delenv("FIRESTORE_DOC", raising=False)
|
|
cfg = Config()
|
|
with pytest.raises(ConfigurationError) as exc_info:
|
|
cfg.load_and_validate_firestore_doc()
|
|
assert "Environment variable 'FIRESTORE_DOC' is required" in str(exc_info.value)
|
|
|
|
|
|
def test_load_and_validate_firestore_doc_invalid_json(monkeypatch):
|
|
"""Tests error handling when FIRESTORE_DOC is not valid JSON."""
|
|
monkeypatch.setenv("FIRESTORE_DOC", "{invalid json string")
|
|
cfg = Config()
|
|
with pytest.raises(ConfigurationError) as exc_info:
|
|
cfg.load_and_validate_firestore_doc()
|
|
assert "Failed to parse 'FIRESTORE_DOC' as JSON" in str(exc_info.value)
|
|
|
|
|
|
def test_load_and_validate_firestore_doc_non_dict(monkeypatch):
|
|
"""Tests error handling when FIRESTORE_DOC parses to a non-dict JSON structure."""
|
|
monkeypatch.setenv("FIRESTORE_DOC", '["array_item1", "array_item2"]')
|
|
cfg = Config()
|
|
with pytest.raises(ConfigurationError) as exc_info:
|
|
cfg.load_and_validate_firestore_doc()
|
|
assert "Firestore document specification must be a JSON object" in str(exc_info.value)
|