Files
nomad/helper/users/dynamic/pool_test.go
Seth Hoenig 57bd39061b exec2: implement a dynamic users pool (#20065)
* exec2: implement a dynamic users pool

This PR adds an implementation of a Pool from which dynamic users can
be allocated on behalf of tasks making use of an upcoming feature of
Nomad client (dynamic users).

A task hook and client plumbing, etc. will be in follow up PRs.

* no need for randomness assertion
2024-03-05 07:35:20 -06:00

120 lines
2.1 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
//go:build linux
package dynamic
import (
"fmt"
"slices"
"testing"
"github.com/shoenig/test/must"
)
var testPoolConfig = &PoolConfig{
MinUGID: 200,
MaxUGID: 209,
}
func TestPool_Release_unused(t *testing.T) {
p := New(testPoolConfig)
cases := []struct {
id UGID
}{
{id: 0},
{id: 200},
{id: 205},
{id: 209},
{id: 210},
}
for _, tc := range cases {
t.Run(fmt.Sprintf("id%s", tc.id), func(t *testing.T) {
err := p.Release(tc.id)
must.ErrorIs(t, ErrReleaseUnused, err)
})
}
}
func TestPool_Acquire_exhausted(t *testing.T) {
p := New(testPoolConfig)
// consume all 10 ugids
for i := 200; i <= 209; i++ {
v, err := p.Acquire()
must.NoError(t, err)
must.Between[UGID](t, 200, v, 209)
}
// next acquire should fail
v, err := p.Acquire()
must.Eq(t, none, v)
must.ErrorIs(t, ErrPoolExhausted, err)
// let go of one ugid
err2 := p.Release(204)
must.NoError(t, err2)
// now an acquire should succeed
v2, err3 := p.Acquire()
must.NoError(t, err3)
must.Eq(t, 204, v2)
}
func TestPool_Acquire_random(t *testing.T) {
run1 := make([]UGID, 10)
run2 := make([]UGID, 10)
p1 := New(testPoolConfig)
p2 := New(testPoolConfig)
// acquire all 10 UGIDs and record the order of each
for i := 0; i < 10; i++ {
v1, err1 := p1.Acquire()
must.NoError(t, err1)
v2, err2 := p2.Acquire()
must.NoError(t, err2)
run1[i] = v1
run2[i] = v2
}
// ensure both runs contain the expected ugids
exp := []UGID{200, 201, 202, 203, 204, 205, 206, 207, 208, 209}
must.SliceContainsAll(t, exp, run1)
must.SliceContainsAll(t, exp, run2)
}
func TestPool_Restore(t *testing.T) {
p := New(&PoolConfig{
MinUGID: 500,
MaxUGID: 505,
}) // 6 GUIDs
// restore 501, 502, 504
p.Restore(501)
p.Restore(502)
p.Restore(504)
v1, err1 := p.Acquire()
must.NoError(t, err1)
v2, err2 := p.Acquire()
must.NoError(t, err2)
v3, err3 := p.Acquire()
must.NoError(t, err3)
// ensure the next 3 are the UGIDs that were not already consumed
// and set via Restore
ids := []UGID{v1, v2, v3}
slices.Sort(ids)
must.Eq(t, 500, ids[0])
must.Eq(t, 503, ids[1])
must.Eq(t, 505, ids[2])
}