diff --git a/go.mod b/go.mod index 7dfcb1c..4d791ec 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ go 1.19 require ( github.com/apparentlymart/go-cidr v1.1.0 + github.com/deckarep/golang-set/v2 v2.1.0 github.com/hashicorp/go-version v1.6.0 github.com/hashicorp/terraform-plugin-docs v0.13.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.25.0 @@ -58,7 +59,7 @@ require ( github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/oklog/run v1.1.0 // indirect github.com/posener/complete v1.2.3 // indirect - github.com/rogpeppe/go-internal v1.8.1 // indirect + github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/russross/blackfriday v1.6.0 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/spf13/cast v1.5.0 // indirect diff --git a/go.sum b/go.sum index 0914850..13cd69f 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI= +github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -174,7 +176,6 @@ github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= github.com/paultyng/go-unifi v1.32.0 h1:k3zHkL57JEmzghRgvvRuDTSkw9CtD10zdxCB9OUweYI= github.com/paultyng/go-unifi v1.32.0/go.mod h1:i8D+gyo5NinnDlQ5ZGdqSvRqRyHuV4zA2CLZnHb0axE= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -182,8 +183,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= -github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww= github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY= github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4= @@ -317,7 +318,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/internal/provider/resource_device_test.go b/internal/provider/resource_device_test.go index bfcdc34..faa18d7 100644 --- a/internal/provider/resource_device_test.go +++ b/internal/provider/resource_device_test.go @@ -6,27 +6,24 @@ import ( "regexp" "sync" "testing" + "time" + mapset "github.com/deckarep/golang-set/v2" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/paultyng/go-unifi/unifi" ) var ( - deviceLock sync.Mutex - devicesAvailable []string - devicesInitialized bool = false + deviceInit sync.Once + devicePool mapset.Set[*unifi.Device] = mapset.NewSet[*unifi.Device]() ) func allocateDevice(t *testing.T) (string, func()) { - deviceLock.Lock() - defer deviceLock.Unlock() + ctx := context.Background() - if !devicesInitialized { - devicesAvailable = []string{} - devicesInitialized = true - - devices, err := testClient.ListDevice(context.Background(), "default") + deviceInit.Do(func() { + devices, err := testClient.ListDevice(ctx, "default") if err != nil { t.Fatalf("Error listing devices: %s", err) } @@ -41,25 +38,37 @@ func allocateDevice(t *testing.T) (string, func()) { continue } - devicesAvailable = append(devicesAvailable, device.MAC) + d := device + if ok := devicePool.Add(&d); !ok { + t.Fatal("Failed to add device to pool") + } + } + }) + + var device *unifi.Device + + err := resource.RetryContext(ctx, 1*time.Minute, func() *resource.RetryError { + var ok bool + device, ok = devicePool.Pop() + + if device == nil || !ok { + return resource.RetryableError(fmt.Errorf("Unable to allocate test device")) + } + + return nil + }) + + if err != nil { + t.Fatal(err) + } + + unallocate := func() { + if ok := devicePool.Add(device); !ok { + t.Fatal("Failed to add device to pool") } } - if len(devicesAvailable) == 0 { - t.Fatal("Unable to allocate test device") - } - - var device string - device, devicesAvailable = devicesAvailable[0], devicesAvailable[1:] - - unallocate := func() { - deviceLock.Lock() - defer deviceLock.Unlock() - - devicesAvailable = append(devicesAvailable, device) - } - - return device, unallocate + return device.MAC, unallocate } func preCheckDeviceExists(t *testing.T, site, mac string) { diff --git a/internal/provider/resource_user_test.go b/internal/provider/resource_user_test.go index c67eb0c..0f3f1cc 100644 --- a/internal/provider/resource_user_test.go +++ b/internal/provider/resource_user_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/apparentlymart/go-cidr/cidr" + mapset "github.com/deckarep/golang-set/v2" "github.com/hashicorp/terraform-plugin-testing/helper/resource" "github.com/hashicorp/terraform-plugin-testing/terraform" "github.com/paultyng/go-unifi/unifi" @@ -20,35 +21,30 @@ func userImportStep(name string) resource.TestStep { } var ( - testMacLock sync.Mutex - testMacsAvailable []*net.HardwareAddr + macInit sync.Once + macPool mapset.Set[*net.HardwareAddr] = mapset.NewSet[*net.HardwareAddr]() ) -// for test MAC addresses, see https://tools.ietf.org/html/rfc7042#section-2.1.2 -func init() { - testMacsAvailable = make([]*net.HardwareAddr, 256) - - for i := 0; i < 256; i++ { - testMacsAvailable[i] = &net.HardwareAddr{0x00, 0x00, 0x5e, 0x00, 0x53, byte(i)} - } -} - func allocateTestMac(t *testing.T) (string, func()) { - testMacLock.Lock() - defer testMacLock.Unlock() + macInit.Do(func() { + // for test MAC addresses, see https://tools.ietf.org/html/rfc7042#section-2.1. + for i := 0; i < 256; i++ { + mac := net.HardwareAddr{0x00, 0x00, 0x5e, 0x00, 0x53, byte(i)} + if ok := macPool.Add(&mac); !ok { + t.Fatal("Failed to add MAC to pool") + } + } + }) - if len(testMacsAvailable) == 0 { + mac, ok := macPool.Pop() + if mac == nil || !ok { t.Fatal("Unable to allocate test MAC") } - var mac *net.HardwareAddr - mac, testMacsAvailable = testMacsAvailable[0], testMacsAvailable[1:] - unallocate := func() { - testMacLock.Lock() - defer testMacLock.Unlock() - - testMacsAvailable = append(testMacsAvailable, mac) //nolint:makezero + if ok := macPool.Add(mac); !ok { + t.Fatal("Failed to add MAC to pool") + } } return mac.String(), unallocate