@@ -2,6 +2,8 @@ package vz_test
22
33import (
44 "log"
5+ "os"
6+ "os/exec"
57 "path/filepath"
68 "strings"
79 "testing"
@@ -103,3 +105,92 @@ func TestBlockDeviceWithCacheAndSyncMode(t *testing.T) {
103105 t .Fatalf ("want state %v but got %v" , vz .VirtualMachineStateRunning , got )
104106 }
105107}
108+
109+ func TestBlockDeviceStorageDeviceAttachmentError (t * testing.T ) {
110+ if vz .Available (14 ) {
111+ t .Skip ("vz.NewDiskBlockDeviceStorageDeviceAttachment is supported from macOS 14" )
112+ }
113+
114+ f , err := os .Create (filepath .Join (t .TempDir (), "empty" ))
115+ if err != nil {
116+ t .Fatal (err )
117+ }
118+ f .Close ()
119+ _ , err = vz .NewDiskBlockDeviceStorageDeviceAttachment (f , false , vz .DiskSynchronizationModeNone )
120+ if err == nil {
121+ t .Fatal ("did not get an error with invalid file descriptor" )
122+ }
123+ }
124+
125+ func TestBlockDeviceWithDeviceAttachment (t * testing.T ) {
126+ if vz .Available (12 ) {
127+ t .Skip ("vz.NewDiskImageStorageDeviceAttachmentWithCacheAndSync is supported from macOS 12" )
128+ }
129+
130+ devPath := ""
131+ container := newVirtualizationMachine (t ,
132+ func (vmc * vz.VirtualMachineConfiguration ) error {
133+ dir := t .TempDir ()
134+ path := filepath .Join (dir , "disk.img" )
135+ if err := vz .CreateDiskImage (path , 512 ); err != nil {
136+ t .Fatal (err )
137+ }
138+ cmd := exec .Command ("hdiutil" , "attach" , "-imagekey" , "diskimage-class=CRawDiskImage" , "-nomount" , path )
139+ output , err := cmd .Output ()
140+ if err != nil {
141+ t .Fatalf ("failed to attach disk image: %v" , err )
142+ }
143+
144+ outputStr := string (output )
145+ lines := strings .Split (outputStr , "\n " )
146+ if len (lines ) == 0 || ! strings .HasPrefix (lines [0 ], "/dev/" ) {
147+ log .Printf ("[%s]\n " , lines )
148+ t .Fatalf ("unexpected output from `hdiutil attach`" )
149+ }
150+ if len (lines ) != 0 && strings .HasPrefix (lines [0 ], "/dev/" ) {
151+ devPath = strings .TrimSpace (lines [0 ])
152+ }
153+
154+ var attachment * vz.DiskBlockDeviceStorageDeviceAttachment
155+ {
156+ dev , err := os .Open (devPath )
157+ if err != nil {
158+ t .Fatal (err )
159+ }
160+
161+ attachment , err = vz .NewDiskBlockDeviceStorageDeviceAttachment (dev , false , vz .DiskSynchronizationModeNone )
162+ if err != nil {
163+ t .Fatal (err )
164+ }
165+ if err := dev .Close (); err != nil {
166+ log .Printf ("failed to close %s: %s\n " , devPath , err )
167+ }
168+
169+ }
170+
171+ config , err := vz .NewVirtioBlockDeviceConfiguration (attachment )
172+ if err != nil {
173+ t .Fatal (err )
174+ }
175+ vmc .SetStorageDevicesVirtualMachineConfiguration ([]vz.StorageDeviceConfiguration {
176+ config ,
177+ })
178+ return nil
179+ },
180+ )
181+ t .Cleanup (func () {
182+ if err := container .Shutdown (); err != nil {
183+ log .Println (err )
184+ }
185+ cmd := exec .Command ("hdiutil" , "detach" , devPath )
186+ if err := cmd .Run (); err != nil {
187+ log .Printf ("hdiutil detach %s failed: %s\n " , devPath , err )
188+ }
189+ })
190+
191+ vm := container .VirtualMachine
192+
193+ if got := vm .State (); vz .VirtualMachineStateRunning != got {
194+ t .Fatalf ("want state %v but got %v" , vz .VirtualMachineStateRunning , got )
195+ }
196+ }
0 commit comments