From b918bbaf931da7fc1468e37208b4566f78ebc9be Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Thu, 13 Oct 2022 16:39:50 +0900 Subject: [PATCH 1/5] fixed some code related to check available version Version checking within the method is basically treated as if it has already been done. However, if the version that the calling struct can handle is different from the version that the method can handle, version checking is performed on the method. --- configuration.go | 17 +++------ osversion.go | 37 ++++++++++++++++++++ virtualization.go | 77 +++++------------------------------------ virtualization_arm64.go | 42 +++++++--------------- 4 files changed, 63 insertions(+), 110 deletions(-) create mode 100644 osversion.go diff --git a/configuration.go b/configuration.go index 6cde2b0..a56c2ee 100644 --- a/configuration.go +++ b/configuration.go @@ -37,12 +37,12 @@ type VirtualMachineConfiguration struct { // NewVirtualMachineConfiguration creates a new configuration. // -// - bootLoader parameter is used when the virtual machine starts. -// - cpu parameter is The number of CPUs must be a value between +// - bootLoader parameter is used when the virtual machine starts. +// - cpu parameter is The number of CPUs must be a value between // VZVirtualMachineConfiguration.minimumAllowedCPUCount and VZVirtualMachineConfiguration.maximumAllowedCPUCount. -// - memorySize parameter represents memory size in bytes. -// The memory size must be a multiple of a 1 megabyte (1024 * 1024 bytes) between -// VZVirtualMachineConfiguration.minimumAllowedMemorySize and VZVirtualMachineConfiguration.maximumAllowedMemorySize. +// - memorySize parameter represents memory size in bytes. +// The memory size must be a multiple of a 1 megabyte (1024 * 1024 bytes) between +// VZVirtualMachineConfiguration.minimumAllowedMemorySize and VZVirtualMachineConfiguration.maximumAllowedMemorySize. // // This is only supported on macOS 11 and newer, ErrUnsupportedOSVersion will // be returned on older versions. @@ -72,14 +72,7 @@ func NewVirtualMachineConfiguration(bootLoader BootLoader, cpu uint, memorySize // // Return true if the configuration is valid. // If error is not nil, assigned with the validation error if the validation failed. -// -// This is only supported on macOS 11 and newer, ErrUnsupportedOSVersion will -// be returned on older versions. func (v *VirtualMachineConfiguration) Validate() (bool, error) { - if macosMajorVersionLessThan(11) { - return false, ErrUnsupportedOSVersion - } - nserr := newNSErrorAsNil() nserrPtr := nserr.Ptr() ret := C.validateVZVirtualMachineConfiguration(v.Ptr(), &nserrPtr) diff --git a/osversion.go b/osversion.go new file mode 100644 index 0000000..e389af1 --- /dev/null +++ b/osversion.go @@ -0,0 +1,37 @@ +package vz + +import ( + "strconv" + "strings" + "sync" + "syscall" +) + +func macosMajorVersionLessThan(major int) bool { + return macOSMajorVersion() < major +} + +var ( + majorVersion int + majorVersionOnce interface{ Do(func()) } = &sync.Once{} +) + +// This can be replaced in the test code to enable mock. +// It will not be changed in production. +var fetchMajorVersion = func() { + osver, err := syscall.Sysctl("kern.osproductversion") + if err != nil { + panic(err) + } + osverArray := strings.Split(osver, ".") + major, err := strconv.Atoi(osverArray[0]) + if err != nil { + panic(err) + } + majorVersion = major +} + +func macOSMajorVersion() int { + majorVersionOnce.Do(fetchMajorVersion) + return majorVersion +} diff --git a/virtualization.go b/virtualization.go index 5963c7f..60eedb0 100644 --- a/virtualization.go +++ b/virtualization.go @@ -10,10 +10,7 @@ import ( "errors" "runtime" "runtime/cgo" - "strconv" - "strings" "sync" - "syscall" "unsafe" ) @@ -194,37 +191,21 @@ func (v *VirtualMachine) StateChangedNotify() <-chan VirtualMachineState { // CanStart returns true if the machine is in a state that can be started. func (v *VirtualMachine) CanStart() bool { - if macosMajorVersionLessThan(11) { - return false - } - return bool(C.vmCanStart(v.Ptr(), v.dispatchQueue)) } // CanPause returns true if the machine is in a state that can be paused. func (v *VirtualMachine) CanPause() bool { - if macosMajorVersionLessThan(11) { - return false - } - return bool(C.vmCanPause(v.Ptr(), v.dispatchQueue)) } // CanResume returns true if the machine is in a state that can be resumed. func (v *VirtualMachine) CanResume() bool { - if macosMajorVersionLessThan(11) { - return false - } - return (bool)(C.vmCanResume(v.Ptr(), v.dispatchQueue)) } // CanRequestStop returns whether the machine is in a state where the guest can be asked to stop. func (v *VirtualMachine) CanRequestStop() bool { - if macosMajorVersionLessThan(11) { - return false - } - return (bool)(C.vmCanRequestStop(v.Ptr(), v.dispatchQueue)) } @@ -236,7 +217,6 @@ func (v *VirtualMachine) CanStop() bool { if macosMajorVersionLessThan(12) { return false } - return (bool)(C.vmCanStop(v.Ptr(), v.dispatchQueue)) } @@ -269,11 +249,6 @@ func makeHandler(fn func(error)) (func(error), chan struct{}) { // This is only supported on macOS 11 and newer, on older versions fn will be called immediately // with ErrUnsupportedOSVersion. func (v *VirtualMachine) Start(fn func(error)) { - if macosMajorVersionLessThan(11) { - fn(ErrUnsupportedOSVersion) - return - } - h, done := makeHandler(fn) handler := cgo.NewHandle(h) defer handler.Delete() @@ -289,11 +264,6 @@ func (v *VirtualMachine) Start(fn func(error)) { // This is only supported on macOS 11 and newer, on older versions fn will be called immediately // with ErrUnsupportedOSVersion. func (v *VirtualMachine) Pause(fn func(error)) { - if macosMajorVersionLessThan(11) { - fn(ErrUnsupportedOSVersion) - return - } - h, done := makeHandler(fn) handler := cgo.NewHandle(h) defer handler.Delete() @@ -309,11 +279,6 @@ func (v *VirtualMachine) Pause(fn func(error)) { // This is only supported on macOS 11 and newer, on older versions fn will be called immediately // with ErrUnsupportedOSVersion. func (v *VirtualMachine) Resume(fn func(error)) { - if macosMajorVersionLessThan(11) { - fn(ErrUnsupportedOSVersion) - return - } - h, done := makeHandler(fn) handler := cgo.NewHandle(h) defer handler.Delete() @@ -329,10 +294,6 @@ func (v *VirtualMachine) Resume(fn func(error)) { // This is only supported on macOS 11 and newer, ErrUnsupportedOSVersion will // be returned on older versions. func (v *VirtualMachine) RequestStop() (bool, error) { - if macosMajorVersionLessThan(11) { - return false, ErrUnsupportedOSVersion - } - nserr := newNSErrorAsNil() nserrPtr := nserr.Ptr() ret := (bool)(C.requestStopVirtualMachine(v.Ptr(), v.dispatchQueue, &nserrPtr)) @@ -367,35 +328,13 @@ func (v *VirtualMachine) Stop(fn func(error)) { // StartGraphicApplication starts an application to display graphics of the VM. // // You must to call runtime.LockOSThread before calling this method. -func (v *VirtualMachine) StartGraphicApplication(width, height float64) { - C.startVirtualMachineWindow(v.Ptr(), C.double(width), C.double(height)) -} - -func macosMajorVersionLessThan(major int) bool { - return macOSMajorVersion() < major -} - -var ( - majorVersion int - majorVersionOnce sync.Once -) - -// This can be replaced in the test code to enable mock. -// It will not be changed in production. -var fetchMajorVersion = func() { - osver, err := syscall.Sysctl("kern.osproductversion") - if err != nil { - panic(err) - } - osverArray := strings.Split(osver, ".") - major, err := strconv.Atoi(osverArray[0]) - if err != nil { - panic(err) +// +// This is only supported on macOS 12 and newer, on older versions fn will be called immediately +// with ErrUnsupportedOSVersion. +func (v *VirtualMachine) StartGraphicApplication(width, height float64) error { + if macosMajorVersionLessThan(12) { + return ErrUnsupportedOSVersion } - majorVersion = major -} - -func macOSMajorVersion() int { - majorVersionOnce.Do(fetchMajorVersion) - return majorVersion + C.startVirtualMachineWindow(v.Ptr(), C.double(width), C.double(height)) + return nil } diff --git a/virtualization_arm64.go b/virtualization_arm64.go index 67798a1..ab704aa 100644 --- a/virtualization_arm64.go +++ b/virtualization_arm64.go @@ -58,21 +58,14 @@ func NewMacHardwareModelWithData(b []byte) (*MacHardwareModel, error) { unsafe.Pointer(&b[0]), C.int(len(b)), ) - ret, err := newMacHardwareModel(ptr) - if err != nil { - return nil, err - } + ret := newMacHardwareModel(ptr) runtime.SetFinalizer(ret, func(self *MacHardwareModel) { self.Release() }) return ret, nil } -func newMacHardwareModel(ptr unsafe.Pointer) (*MacHardwareModel, error) { - if macosMajorVersionLessThan(12) { - return nil, ErrUnsupportedOSVersion - } - +func newMacHardwareModel(ptr unsafe.Pointer) *MacHardwareModel { ret := C.convertVZMacHardwareModel2Struct(ptr) dataRepresentation := ret.dataRepresentation bytePointer := (*byte)(unsafe.Pointer(dataRepresentation.ptr)) @@ -83,7 +76,7 @@ func newMacHardwareModel(ptr unsafe.Pointer) (*MacHardwareModel, error) { supported: bool(ret.supported), // https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices dataRepresentation: unsafe.Slice(bytePointer, dataRepresentation.len), - }, nil + } } // Supported indicate whether this hardware model is supported by the host. @@ -125,7 +118,7 @@ func NewMacMachineIdentifierWithData(b []byte) (*MacMachineIdentifier, error) { unsafe.Pointer(&b[0]), C.int(len(b)), ) - return newMacMachineIdentifier(ptr) + return newMacMachineIdentifier(ptr), nil } // NewMacMachineIdentifier initialize a new Mac machine identifier is used by macOS guests to uniquely @@ -140,14 +133,13 @@ func NewMacMachineIdentifierWithData(b []byte) (*MacMachineIdentifier, error) { // This is only supported on macOS 12 and newer, ErrUnsupportedOSVersion will // be returned on older versions. func NewMacMachineIdentifier() (*MacMachineIdentifier, error) { - return newMacMachineIdentifier(C.newVZMacMachineIdentifier()) -} - -func newMacMachineIdentifier(ptr unsafe.Pointer) (*MacMachineIdentifier, error) { if macosMajorVersionLessThan(12) { return nil, ErrUnsupportedOSVersion } + return newMacMachineIdentifier(C.newVZMacMachineIdentifier()), nil +} +func newMacMachineIdentifier(ptr unsafe.Pointer) *MacMachineIdentifier { dataRepresentation := C.getVZMacMachineIdentifierDataRepresentation(ptr) bytePointer := (*byte)(unsafe.Pointer(dataRepresentation.ptr)) return &MacMachineIdentifier{ @@ -156,7 +148,7 @@ func newMacMachineIdentifier(ptr unsafe.Pointer) (*MacMachineIdentifier, error) }, // https://github.com/golang/go/wiki/cgo#turning-c-arrays-into-go-slices dataRepresentation: unsafe.Slice(bytePointer, dataRepresentation.len), - }, nil + } } // DataRepresentation opaque data representation of the machine identifier. @@ -268,31 +260,25 @@ func (m *MacOSRestoreImage) OperatingSystemVersion() OperatingSystemVersion { // configuration requirements that will provide the most complete feature set on the current host. // If none of the hardware models are supported on the current host, this property is nil. func (m *MacOSRestoreImage) MostFeaturefulSupportedConfiguration() *MacOSConfigurationRequirements { - // ignoring ErrUnsupportedOSVersion, it's already returned when trying to create a MacOSRestoreImage - config, _ := newMacOSConfigurationRequirements(m.mostFeaturefulSupportedConfigurationPtr) - return config + return newMacOSConfigurationRequirements(m.mostFeaturefulSupportedConfigurationPtr) } // MacOSConfigurationRequirements describes the parameter constraints required by a specific configuration of macOS. // -// When a VZMacOSRestoreImage is loaded, it can be inspected to determine the configurations supported by that restore image. +// When a VZMacOSRestoreImage is loaded, it can be inspected to determine the configurations supported by that restore image. type MacOSConfigurationRequirements struct { minimumSupportedCPUCount uint64 minimumSupportedMemorySize uint64 hardwareModelPtr unsafe.Pointer } -func newMacOSConfigurationRequirements(ptr unsafe.Pointer) (*MacOSConfigurationRequirements, error) { - if macosMajorVersionLessThan(12) { - return nil, ErrUnsupportedOSVersion - } - +func newMacOSConfigurationRequirements(ptr unsafe.Pointer) *MacOSConfigurationRequirements { ret := C.convertVZMacOSConfigurationRequirements2Struct(ptr) return &MacOSConfigurationRequirements{ minimumSupportedCPUCount: uint64(ret.minimumSupportedCPUCount), minimumSupportedMemorySize: uint64(ret.minimumSupportedMemorySize), hardwareModelPtr: ret.hardwareModel, - }, nil + } } // HardwareModel returns the hardware model for this configuration. @@ -301,9 +287,7 @@ func newMacOSConfigurationRequirements(ptr unsafe.Pointer) (*MacOSConfigurationR // Use VZMacPlatformConfiguration.hardwareModel to configure the Mac platform, and // Use `WithCreatingStorage` functional option of the `NewMacAuxiliaryStorage` to create its auxiliary storage. func (m *MacOSConfigurationRequirements) HardwareModel() *MacHardwareModel { - // ignoring ErrUnsupportedOSVersion, it's already returned when trying to create a MacOSConfigurationRequirements - model, _ := newMacHardwareModel(m.hardwareModelPtr) - return model + return newMacHardwareModel(m.hardwareModelPtr) } // MinimumSupportedCPUCount returns the minimum supported number of CPUs for this configuration. From e77fe1dde01efab6271bff3a2be5357cd7007690 Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Thu, 13 Oct 2022 16:43:07 +0900 Subject: [PATCH 2/5] added some tests for available versions --- osversion_arm64_test.go | 71 ++++++++++++++++++ osversion_test.go | 157 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 228 insertions(+) create mode 100644 osversion_arm64_test.go create mode 100644 osversion_test.go diff --git a/osversion_arm64_test.go b/osversion_arm64_test.go new file mode 100644 index 0000000..319fedc --- /dev/null +++ b/osversion_arm64_test.go @@ -0,0 +1,71 @@ +package vz + +import ( + "context" + "errors" + "sync" + "testing" +) + +func TestAvailableVersionArm64(t *testing.T) { + majorVersionOnce = &nopDoer{} + defer func() { + majorVersion = 0 + majorVersionOnce = &sync.Once{} + }() + t.Run("macOS 12", func(t *testing.T) { + majorVersion = 11 + cases := map[string]func() error{ + "NewMacOSBootLoader": func() error { + _, err := NewMacOSBootLoader() + return err + }, + "NewMacGraphicsDeviceConfiguration": func() error { + _, err := NewMacGraphicsDeviceConfiguration() + return err + }, + "NewMacGraphicsDisplayConfiguration": func() error { + _, err := NewMacGraphicsDisplayConfiguration(0, 0, 0) + return err + }, + "NewMacPlatformConfiguration": func() error { + _, err := NewMacPlatformConfiguration() + return err + }, + "NewMacHardwareModelWithData": func() error { + _, err := NewMacHardwareModelWithData(nil) + return err + }, + "NewMacMachineIdentifierWithData": func() error { + _, err := NewMacMachineIdentifierWithData(nil) + return err + }, + "NewMacMachineIdentifier": func() error { + _, err := NewMacMachineIdentifier() + return err + }, + "NewMacAuxiliaryStorage": func() error { + _, err := NewMacAuxiliaryStorage("") + return err + }, + "FetchLatestSupportedMacOSRestoreImage": func() error { + _, err := FetchLatestSupportedMacOSRestoreImage(context.Background(), "") + return err + }, + "LoadMacOSRestoreImageFromPath": func() error { + _, err := LoadMacOSRestoreImageFromPath("") + return err + }, + "NewMacOSInstaller": func() error { + _, err := NewMacOSInstaller(nil, "") + return err + }, + } + for name, fn := range cases { + err := fn() + if !errors.Is(err, ErrUnsupportedOSVersion) { + t.Fatalf("unexpected error %v in %s", err, name) + } + } + }) +} diff --git a/osversion_test.go b/osversion_test.go new file mode 100644 index 0000000..16d12d5 --- /dev/null +++ b/osversion_test.go @@ -0,0 +1,157 @@ +package vz + +import ( + "errors" + "sync" + "testing" +) + +type nopDoer struct{} + +func (*nopDoer) Do(func()) {} + +func TestAvailableVersion(t *testing.T) { + majorVersionOnce = &nopDoer{} + defer func() { + majorVersion = 0 + majorVersionOnce = &sync.Once{} + }() + + t.Run("macOS 11", func(t *testing.T) { + majorVersion = 10 + cases := map[string]func() error{ + "NewLinuxBootLoader": func() error { + _, err := NewLinuxBootLoader("") + return err + }, + "NewVirtualMachineConfiguration": func() error { + _, err := NewVirtualMachineConfiguration(nil, 0, 0) + return err + }, + "NewFileHandleSerialPortAttachment": func() error { + _, err := NewFileHandleSerialPortAttachment(nil, nil) + return err + }, + "NewFileSerialPortAttachment": func() error { + _, err := NewFileSerialPortAttachment("", false) + return err + }, + "NewVirtioConsoleDeviceSerialPortConfiguration": func() error { + _, err := NewVirtioConsoleDeviceSerialPortConfiguration(nil) + return err + }, + "NewVirtioEntropyDeviceConfiguration": func() error { + _, err := NewVirtioEntropyDeviceConfiguration() + return err + }, + "NewVirtioTraditionalMemoryBalloonDeviceConfiguration": func() error { + _, err := NewVirtioTraditionalMemoryBalloonDeviceConfiguration() + return err + }, + "NewNATNetworkDeviceAttachment": func() error { + _, err := NewNATNetworkDeviceAttachment() + return err + }, + "NewBridgedNetworkDeviceAttachment": func() error { + _, err := NewBridgedNetworkDeviceAttachment(nil) + return err + }, + "NewFileHandleNetworkDeviceAttachment": func() error { + _, err := NewFileHandleNetworkDeviceAttachment(nil) + return err + }, + "NewVirtioNetworkDeviceConfiguration": func() error { + _, err := NewVirtioNetworkDeviceConfiguration(nil) + return err + }, + "NewMACAddress": func() error { + _, err := NewMACAddress(nil) + return err + }, + "NewRandomLocallyAdministeredMACAddress": func() error { + _, err := NewRandomLocallyAdministeredMACAddress() + return err + }, + "NewVirtioSocketDeviceConfiguration": func() error { + _, err := NewVirtioSocketDeviceConfiguration() + return err + }, + "NewVirtioSocketListener": func() error { + _, err := NewVirtioSocketListener(nil) + return err + }, + "NewDiskImageStorageDeviceAttachment": func() error { + _, err := NewDiskImageStorageDeviceAttachment("", false) + return err + }, + "NewVirtioBlockDeviceConfiguration": func() error { + _, err := NewVirtioBlockDeviceConfiguration(nil) + return err + }, + "NewVirtualMachine": func() error { + _, err := NewVirtualMachine(nil) + return err + }, + } + for name, fn := range cases { + err := fn() + if !errors.Is(err, ErrUnsupportedOSVersion) { + t.Fatalf("unexpected error %v in %s", err, name) + } + } + }) + + t.Run("macOS 12", func(t *testing.T) { + majorVersion = 11 + cases := map[string]func() error{ + "NewVirtioSoundDeviceConfiguration": func() error { + _, err := NewVirtioSoundDeviceConfiguration() + return err + }, + "NewVirtioSoundDeviceHostInputStreamConfiguration": func() error { + _, err := NewVirtioSoundDeviceHostInputStreamConfiguration() + return err + }, + "NewVirtioSoundDeviceHostOutputStreamConfiguration": func() error { + _, err := NewVirtioSoundDeviceHostOutputStreamConfiguration() + return err + }, + "NewUSBKeyboardConfiguration": func() error { + _, err := NewUSBKeyboardConfiguration() + return err + }, + "NewGenericPlatformConfiguration": func() error { + _, err := NewGenericPlatformConfiguration() + return err + }, + "NewUSBScreenCoordinatePointingDeviceConfiguration": func() error { + _, err := NewUSBScreenCoordinatePointingDeviceConfiguration() + return err + }, + "NewVirtioFileSystemDeviceConfiguration": func() error { + _, err := NewVirtioFileSystemDeviceConfiguration("") + return err + }, + "NewSharedDirectory": func() error { + _, err := NewSharedDirectory("", false) + return err + }, + "(*VirtualMachine).Stop": func() error { + var err error + (*VirtualMachine)(nil).Stop(func(e error) { + err = e + }) + return err + }, + "(*VirtualMachine).StartGraphicApplication": func() error { + return (*VirtualMachine)(nil).StartGraphicApplication(0, 0) + }, + } + for name, fn := range cases { + err := fn() + if !errors.Is(err, ErrUnsupportedOSVersion) { + t.Fatalf("unexpected error %v in %s", err, name) + } + } + }) +} From aa76faf3aa3bc1f7377d1fdf4dcd1f1baed3d4a3 Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Thu, 13 Oct 2022 16:48:09 +0900 Subject: [PATCH 3/5] removed type on ErrUnsupportedOSVersion declare --- virtualization.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/virtualization.go b/virtualization.go index 60eedb0..0194c8d 100644 --- a/virtualization.go +++ b/virtualization.go @@ -16,7 +16,7 @@ import ( // ErrUnsupportedOSVersion is returned when calling a method which is only // available in newer macOS versions. -var ErrUnsupportedOSVersion error = errors.New("unsupported macOS version") +var ErrUnsupportedOSVersion = errors.New("unsupported macOS version") func init() { C.sharedApplication() From b956baa3197f1be0d5a0fb5a02409c8783d6c868 Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Thu, 13 Oct 2022 16:59:09 +0900 Subject: [PATCH 4/5] added os version validation in shared directories --- osversion_test.go | 8 ++++++++ shared_folder.go | 14 ++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/osversion_test.go b/osversion_test.go index 16d12d5..880a8f3 100644 --- a/osversion_test.go +++ b/osversion_test.go @@ -136,6 +136,14 @@ func TestAvailableVersion(t *testing.T) { _, err := NewSharedDirectory("", false) return err }, + "NewSingleDirectoryShare": func() error { + _, err := NewSingleDirectoryShare(nil) + return err + }, + "NewMultipleDirectoryShare": func() error { + _, err := NewMultipleDirectoryShare(nil) + return err + }, "(*VirtualMachine).Stop": func() error { var err error (*VirtualMachine)(nil).Stop(func(e error) { diff --git a/shared_folder.go b/shared_folder.go index 7bd7ca0..32ccab1 100644 --- a/shared_folder.go +++ b/shared_folder.go @@ -103,7 +103,10 @@ type SingleDirectoryShare struct { } // NewSingleDirectoryShare creates a new single directory share. -func NewSingleDirectoryShare(share *SharedDirectory) *SingleDirectoryShare { +func NewSingleDirectoryShare(share *SharedDirectory) (*SingleDirectoryShare, error) { + if macosMajorVersionLessThan(12) { + return nil, ErrUnsupportedOSVersion + } config := &SingleDirectoryShare{ pointer: pointer{ ptr: C.newVZSingleDirectoryShare(share.Ptr()), @@ -112,7 +115,7 @@ func NewSingleDirectoryShare(share *SharedDirectory) *SingleDirectoryShare { runtime.SetFinalizer(config, func(self *SingleDirectoryShare) { self.Release() }) - return config + return config, nil } // MultipleDirectoryShare defines the directory share for multiple directories. @@ -123,7 +126,10 @@ type MultipleDirectoryShare struct { } // NewMultipleDirectoryShare creates a new multiple directories share. -func NewMultipleDirectoryShare(shares map[string]*SharedDirectory) *MultipleDirectoryShare { +func NewMultipleDirectoryShare(shares map[string]*SharedDirectory) (*MultipleDirectoryShare, error) { + if macosMajorVersionLessThan(12) { + return nil, ErrUnsupportedOSVersion + } directories := make(map[string]NSObject, len(shares)) for k, v := range shares { directories[k] = v @@ -139,5 +145,5 @@ func NewMultipleDirectoryShare(shares map[string]*SharedDirectory) *MultipleDire runtime.SetFinalizer(config, func(self *SingleDirectoryShare) { self.Release() }) - return config + return config, nil } From b9afd3189c8d64c282d1aa650edcfea682f80717 Mon Sep 17 00:00:00 2001 From: Kei Kamikawa Date: Thu, 13 Oct 2022 17:01:53 +0900 Subject: [PATCH 5/5] added unit test in actions --- .github/workflows/compile.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml index a0825d2..4299361 100644 --- a/.github/workflows/compile.yml +++ b/.github/workflows/compile.yml @@ -39,6 +39,8 @@ jobs: uses: actions/setup-go@v2 with: go-version: ${{ matrix.go }} + - name: Unit Test + run: go test ./... - name: Build run: cd example/linux && make - name: vet