@@ -92,6 +92,76 @@ def test_cpu_always_satisfied(self, monkeypatch):
9292 assert LemonadeManager .ensure_ready (device = "cpu" ) is True
9393
9494
95+ class TestGpuValidatedForGroupedKeyShapes :
96+ """A 'gpu' request validates against live Lemonade's grouped-key shapes.
97+
98+ Live Lemonade on Linux/Windows reports AMD/NVIDIA GPUs under a single
99+ grouped key (``amd_gpu``/``nvidia_gpu``) whose value is a *list*, not the
100+ legacy split ``amd_igpu``/``amd_dgpu`` keys. ``_validate_device_requirement``
101+ used to only normalize the macOS ``metal`` key, so a real dGPU under
102+ ``amd_gpu`` fell through to CPU and a ``gpu`` request wrongly raised.
103+ """
104+
105+ def test_gpu_satisfied_on_amd_gpu_list_shape (self , monkeypatch ):
106+ # The reproduction shape: amd_gpu as a list (RX 7900 XTX), amd_npu
107+ # unavailable — same payload live Lemonade returns on Ubuntu.
108+ from gaia .llm .lemonade_manager import LemonadeManager
109+
110+ _patch_lemonade (monkeypatch , "lemonade11_amd_dgpu_windows.json" )
111+ assert LemonadeManager .ensure_ready (device = "gpu" ) is True
112+
113+ def test_gpu_satisfied_on_metal_shape (self , monkeypatch ):
114+ from gaia .llm .lemonade_manager import LemonadeManager
115+
116+ _patch_lemonade (monkeypatch , "lemonade11_metal_macos.json" )
117+ assert LemonadeManager .ensure_ready (device = "gpu" ) is True
118+
119+ def test_gpu_satisfied_on_nvidia_gpu_list_shape (self , monkeypatch ):
120+ from gaia .llm .lemonade_client import LemonadeClient
121+ from gaia .llm .lemonade_manager import LemonadeManager
122+
123+ data = {
124+ "devices" : {
125+ "nvidia_gpu" : [{"available" : True , "name" : "NVIDIA GeForce RTX 4090" }],
126+ "amd_npu" : {"available" : False },
127+ "cpu" : {"available" : True },
128+ }
129+ }
130+ monkeypatch .setattr (
131+ LemonadeClient , "get_status" , lambda self : _make_status (), raising = False
132+ )
133+ monkeypatch .setattr (
134+ LemonadeClient , "get_system_info" , lambda self : data , raising = False
135+ )
136+ assert LemonadeManager .ensure_ready (device = "gpu" ) is True
137+
138+ def test_unavailable_amd_gpu_list_still_fails (self , monkeypatch ):
139+ # Availability floor preserved: a present-but-available:false grouped
140+ # GPU must NOT satisfy a gpu request.
141+ from gaia .llm .lemonade_client import LemonadeClient
142+ from gaia .llm .lemonade_manager import (
143+ HardwareRequirementError ,
144+ LemonadeManager ,
145+ )
146+
147+ data = {
148+ "devices" : {
149+ "amd_gpu" : [{"available" : False , "name" : "AMD Radeon RX 7900 XTX" }],
150+ "amd_npu" : {"available" : False },
151+ "cpu" : {"available" : True },
152+ }
153+ }
154+ monkeypatch .setattr (
155+ LemonadeClient , "get_status" , lambda self : _make_status (), raising = False
156+ )
157+ monkeypatch .setattr (
158+ LemonadeClient , "get_system_info" , lambda self : data , raising = False
159+ )
160+ with pytest .raises (HardwareRequirementError ) as exc :
161+ LemonadeManager .ensure_ready (device = "gpu" )
162+ assert "gpu" in str (exc .value ).lower ()
163+
164+
95165# ── B2: unavailable device fails loudly with an actionable error ──────────────
96166
97167
0 commit comments