test: add real-cache offline GGUF integration checks for #7481

Download unsloth/gemma-3-270m-it-bnb-4bit (~430MB) and verify offline
snapshot resolution and tokenizer load with network blocked. Full unsloth
import tests remain GPU-gated.
This commit is contained in:
Souravrajvi0 2026-07-27 03:11:15 +00:00
commit 82f5551e1a
2 changed files with 163 additions and 0 deletions

View file

@ -0,0 +1,53 @@
#!/usr/bin/env python3
"""Download real Gemma weights and run offline integration tests for #7481.
Example:
python tests/saving/run_offline_gguf_integration.py
python tests/saving/run_offline_gguf_integration.py --download-only
"""
from __future__ import annotations
import os
import subprocess
import sys
from pathlib import Path
REPO = "unsloth/gemma-3-270m-it-bnb-4bit"
CACHE_ROOT = Path(os.environ.get("HF_HOME", "/tmp/hf_offline_test_cache"))
def download():
from huggingface_hub import snapshot_download
os.environ.setdefault("HF_HOME", str(CACHE_ROOT))
path = snapshot_download(REPO, cache_dir=str(CACHE_ROOT / "hub"))
print("cached at", path)
def run_tests():
os.environ.setdefault("HF_HOME", str(CACHE_ROOT))
cmd = [
sys.executable,
"-m",
"pytest",
"tests/saving/test_offline_gguf_vlm_tokenizer_7481.py",
"tests/saving/test_offline_gguf_real_cache_integration.py",
"-q",
]
raise SystemExit(subprocess.call(cmd, cwd=str(Path(__file__).resolve().parents[2])))
def main():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--download-only", action="store_true")
args = parser.parse_args()
download()
if not args.download_only:
run_tests()
if __name__ == "__main__":
main()

View file

@ -0,0 +1,110 @@
"""Integration tests for #7481 using real cached Gemma weights.
Requires a one-time online download:
HF_HOME=/tmp/hf_offline_test_cache python -c \\
"from huggingface_hub import snapshot_download; snapshot_download('unsloth/gemma-3-270m-it-bnb-4bit', cache_dir='/tmp/hf_offline_test_cache/hub')"
No GPU. No full unsloth import (CPU-only hosts cannot import the package graph).
"""
from __future__ import annotations
import os
import socket
from pathlib import Path
import pytest
REPO = "unsloth/gemma-3-270m-it-bnb-4bit"
CACHE_ROOT = Path(os.environ.get("HF_HOME", "/tmp/hf_offline_test_cache"))
def _require_cached_repo():
from huggingface_hub import scan_cache_dir
cache_dir = CACHE_ROOT / "hub"
if not cache_dir.exists():
pytest.skip(f"cache missing at {cache_dir}; run snapshot_download for {REPO}")
repos = [r.repo_id for r in scan_cache_dir(str(cache_dir)).repos]
if REPO not in repos:
pytest.skip(f"{REPO} not in {cache_dir}")
def _block_network(monkeypatch):
def _guard(*args, **kwargs):
raise OSError("network blocked for offline integration test")
monkeypatch.setattr(socket, "socket", _guard)
monkeypatch.setattr(socket, "create_connection", _guard)
monkeypatch.setattr(socket, "getaddrinfo", _guard)
def _offline_env(monkeypatch):
monkeypatch.setenv("HF_HUB_OFFLINE", "1")
monkeypatch.setenv("TRANSFORMERS_OFFLINE", "1")
monkeypatch.setenv("HF_HOME", str(CACHE_ROOT))
def _resolve_snapshot(cache_dir: Path) -> Path:
from huggingface_hub import hf_hub_download
path = hf_hub_download(
REPO,
"tokenizer_config.json",
cache_dir=str(cache_dir),
local_files_only=True,
)
return Path(path).parent
@pytest.mark.integration
def test_real_cached_snapshot_resolves_offline(monkeypatch):
_require_cached_repo()
_offline_env(monkeypatch)
_block_network(monkeypatch)
snap = _resolve_snapshot(CACHE_ROOT / "hub")
assert (snap / "tokenizer.json").is_file()
assert (snap / "tokenizer.model").is_file()
@pytest.mark.integration
def test_real_cached_tokenizer_loads_from_snapshot_not_repo_id(monkeypatch):
"""Mirrors the #7481 fix: load from snapshot dir, not Hub repo id."""
_require_cached_repo()
_offline_env(monkeypatch)
_block_network(monkeypatch)
from transformers import PreTrainedTokenizerFast
snap = _resolve_snapshot(CACHE_ROOT / "hub")
tok = PreTrainedTokenizerFast.from_pretrained(str(snap), local_files_only=True)
assert tok.vocab_size > 0
# Repo-id path is what triggered model_info() offline in #7481; snapshot path is the fix.
assert str(snap) != REPO
assert "/" not in Path(str(snap)).name
@pytest.mark.integration
@pytest.mark.skipif(
os.environ.get("UNSLOTH_INTEGRATION_IMPORT") != "1",
reason="full unsloth import needs GPU host; set UNSLOTH_INTEGRATION_IMPORT=1 to enable",
)
def test_real_cached_unsloth_helpers_offline(monkeypatch):
_require_cached_repo()
_offline_env(monkeypatch)
_block_network(monkeypatch)
from types import SimpleNamespace
from unsloth.models.loader_utils import _load_pretrained_tokenizer_fast
from unsloth.save import _has_tokenizer_model
tok = _load_pretrained_tokenizer_fast(
REPO,
local_files_only=True,
cache_dir=str(CACHE_ROOT / "hub"),
)
assert tok.vocab_size > 0
assert _has_tokenizer_model(SimpleNamespace(name_or_path=REPO, tokenizer=None)) is True