diff --git a/serial_console_test.go b/serial_console_test.go new file mode 100644 index 00000000..9ad87673 --- /dev/null +++ b/serial_console_test.go @@ -0,0 +1,27 @@ +package vz_test + +import ( + "errors" + "os" + "testing" + + "github.com/Code-Hex/vz/v3" + "github.com/Code-Hex/vz/v3/internal/objc" +) + +// TestNewFileHandleSerialPortAttachment guards against a regression where the +// constructor checked the error out-parameter pointer (always non-nil) instead +// of the duplicated file handle, causing it to return a non-nil wrapper around a +// NULL Objective-C object with a nil error. The serial console was silently lost. +func TestNewFileHandleSerialPortAttachment(t *testing.T) { + attachment, err := vz.NewFileHandleSerialPortAttachment(os.Stdin, os.Stderr) + if errors.Is(err, vz.ErrUnsupportedOSVersion) { + t.Skipf("not supported on this macOS version: %v", err) + } + if err != nil { + t.Fatal(err) + } + if objc.Ptr(attachment) == nil { + t.Fatal("attachment wraps a NULL pointer: constructor reported success but built nothing") + } +} diff --git a/virtualization_11.m b/virtualization_11.m index 28060e0f..b3abc137 100644 --- a/virtualization_11.m +++ b/virtualization_11.m @@ -454,12 +454,12 @@ void setStorageDevicesVZVirtualMachineConfiguration(void *config, VZFileHandleSerialPortAttachment *ret; @autoreleasepool { NSFileHandle *fileHandleForReading = newFileHandleDupFd(readFileDescriptor, error); - if (error != nil) { + if (fileHandleForReading == nil) { return nil; } NSFileHandle *fileHandleForWriting = newFileHandleDupFd(writeFileDescriptor, error); - if (error != nil) { + if (fileHandleForWriting == nil) { return nil; } ret = [[VZFileHandleSerialPortAttachment alloc]