@@ -115,6 +115,145 @@ public void testGpuDef_withComplexPciAddress() {
115115 assertTrue (gpuXml .contains ("</hostdev>" ));
116116 }
117117
118+ @ Test
119+ public void testGpuDef_withFullPciAddressDomainZero () {
120+ LibvirtGpuDef gpuDef = new LibvirtGpuDef ();
121+ VgpuTypesInfo pciGpuInfo = new VgpuTypesInfo (
122+ GpuDevice .DeviceType .PCI ,
123+ "passthrough" ,
124+ "passthrough" ,
125+ "0000:00:02.0" ,
126+ "10de" ,
127+ "NVIDIA Corporation" ,
128+ "1b38" ,
129+ "Tesla T4"
130+ );
131+ gpuDef .defGpu (pciGpuInfo );
132+
133+ String gpuXml = gpuDef .toString ();
134+
135+ assertTrue (gpuXml .contains ("<address domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>" ));
136+ }
137+
138+ @ Test
139+ public void testGpuDef_withFullPciAddressNonZeroDomain () {
140+ LibvirtGpuDef gpuDef = new LibvirtGpuDef ();
141+ VgpuTypesInfo pciGpuInfo = new VgpuTypesInfo (
142+ GpuDevice .DeviceType .PCI ,
143+ "passthrough" ,
144+ "passthrough" ,
145+ "0001:65:00.0" ,
146+ "10de" ,
147+ "NVIDIA Corporation" ,
148+ "1b38" ,
149+ "Tesla T4"
150+ );
151+ gpuDef .defGpu (pciGpuInfo );
152+
153+ String gpuXml = gpuDef .toString ();
154+
155+ assertTrue (gpuXml .contains ("<address domain='0x0001' bus='0x65' slot='0x00' function='0x0'/>" ));
156+ }
157+
158+ @ Test
159+ public void testGpuDef_withNvidiaStyleEightDigitDomain () {
160+ // nvidia-smi reports PCI addresses with an 8-digit domain (e.g. "00000001:af:00.1").
161+ // generatePciXml must normalize it to the canonical 4-digit form "0x0001".
162+ LibvirtGpuDef gpuDef = new LibvirtGpuDef ();
163+ VgpuTypesInfo pciGpuInfo = new VgpuTypesInfo (
164+ GpuDevice .DeviceType .PCI ,
165+ "passthrough" ,
166+ "passthrough" ,
167+ "00000001:af:00.1" ,
168+ "10de" ,
169+ "NVIDIA Corporation" ,
170+ "1b38" ,
171+ "Tesla T4"
172+ );
173+ gpuDef .defGpu (pciGpuInfo );
174+
175+ String gpuXml = gpuDef .toString ();
176+
177+ assertTrue (gpuXml .contains ("<address domain='0x0001' bus='0xaf' slot='0x00' function='0x1'/>" ));
178+ }
179+
180+ @ Test
181+ public void testGpuDef_withFullPciAddressVfNonZeroDomain () {
182+ LibvirtGpuDef gpuDef = new LibvirtGpuDef ();
183+ VgpuTypesInfo vfGpuInfo = new VgpuTypesInfo (
184+ GpuDevice .DeviceType .PCI ,
185+ "VF-Profile" ,
186+ "VF-Profile" ,
187+ "0002:81:00.3" ,
188+ "10de" ,
189+ "NVIDIA Corporation" ,
190+ "1eb8" ,
191+ "Tesla T4"
192+ );
193+ gpuDef .defGpu (vfGpuInfo );
194+
195+ String gpuXml = gpuDef .toString ();
196+
197+ // Non-passthrough NVIDIA VFs should be unmanaged
198+ assertTrue (gpuXml .contains ("<hostdev mode='subsystem' type='pci' managed='no' display='off'>" ));
199+ assertTrue (gpuXml .contains ("<address domain='0x0002' bus='0x81' slot='0x00' function='0x3'/>" ));
200+ }
201+
202+ @ Test
203+ public void testGpuDef_withLegacyShortBdfDefaultsDomainToZero () {
204+ // Backward compatibility: short BDF with no domain segment must still
205+ // produce a valid libvirt address with domain 0x0000.
206+ LibvirtGpuDef gpuDef = new LibvirtGpuDef ();
207+ VgpuTypesInfo pciGpuInfo = new VgpuTypesInfo (
208+ GpuDevice .DeviceType .PCI ,
209+ "passthrough" ,
210+ "passthrough" ,
211+ "af:00.0" ,
212+ "10de" ,
213+ "NVIDIA Corporation" ,
214+ "1b38" ,
215+ "Tesla T4"
216+ );
217+ gpuDef .defGpu (pciGpuInfo );
218+
219+ String gpuXml = gpuDef .toString ();
220+
221+ assertTrue (gpuXml .contains ("<address domain='0x0000' bus='0xaf' slot='0x00' function='0x0'/>" ));
222+ }
223+
224+ @ Test
225+ public void testGpuDef_withInvalidBusAddressThrows () {
226+ String [] invalidAddresses = {
227+ "notahex:00.0" , // non-hex bus
228+ "gg:00:02.0" , // non-hex domain
229+ "00:02:03:04" , // too many colon-separated parts
230+ "00" , // missing slot/function
231+ "00:02" , // missing function (no dot)
232+ "00:02.0.1" , // extra dot in ss.f
233+ };
234+ for (String addr : invalidAddresses ) {
235+ LibvirtGpuDef gpuDef = new LibvirtGpuDef ();
236+ VgpuTypesInfo info = new VgpuTypesInfo (
237+ GpuDevice .DeviceType .PCI ,
238+ "passthrough" ,
239+ "passthrough" ,
240+ addr ,
241+ "10de" ,
242+ "NVIDIA Corporation" ,
243+ "1b38" ,
244+ "Tesla T4"
245+ );
246+ gpuDef .defGpu (info );
247+ try {
248+ String ignored = gpuDef .toString ();
249+ fail ("Expected IllegalArgumentException for address: " + addr + " but got: " + ignored );
250+ } catch (IllegalArgumentException e ) {
251+ assertTrue ("Exception message should contain the bad address" ,
252+ e .getMessage ().contains (addr ));
253+ }
254+ }
255+ }
256+
118257 @ Test
119258 public void testGpuDef_withNullDeviceType () {
120259 LibvirtGpuDef gpuDef = new LibvirtGpuDef ();
0 commit comments