2022-08-06 09:52:36 -06:00
|
|
|
package locker_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2023-03-19 08:31:00 -06:00
|
|
|
"errors"
|
2022-08-06 09:52:36 -06:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/matryer/is"
|
|
|
|
|
2023-02-26 22:33:01 -07:00
|
|
|
"go.sour.is/ev/pkg/locker"
|
2022-08-06 09:52:36 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
type config struct {
|
|
|
|
Value string
|
|
|
|
Counter int
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestLocker(t *testing.T) {
|
|
|
|
is := is.New(t)
|
|
|
|
|
|
|
|
value := locker.New(&config{})
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
2023-03-19 08:31:00 -06:00
|
|
|
err := value.Use(ctx, func(ctx context.Context, c *config) error {
|
2022-08-06 09:52:36 -06:00
|
|
|
c.Value = "one"
|
|
|
|
c.Counter++
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
is.NoErr(err)
|
|
|
|
|
|
|
|
c, err := value.Copy(context.Background())
|
|
|
|
|
|
|
|
is.NoErr(err)
|
|
|
|
is.Equal(c.Value, "one")
|
|
|
|
is.Equal(c.Counter, 1)
|
|
|
|
|
|
|
|
wait := make(chan struct{})
|
|
|
|
|
2023-03-19 08:31:00 -06:00
|
|
|
go value.Use(ctx, func(ctx context.Context, c *config) error {
|
2022-08-06 09:52:36 -06:00
|
|
|
c.Value = "two"
|
|
|
|
c.Counter++
|
|
|
|
close(wait)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
<-wait
|
|
|
|
cancel()
|
|
|
|
|
2023-03-19 08:31:00 -06:00
|
|
|
err = value.Use(ctx, func(ctx context.Context, c *config) error {
|
2022-08-06 09:52:36 -06:00
|
|
|
c.Value = "three"
|
|
|
|
c.Counter++
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
is.True(err != nil)
|
|
|
|
|
|
|
|
c, err = value.Copy(context.Background())
|
|
|
|
|
|
|
|
is.NoErr(err)
|
|
|
|
is.Equal(c.Value, "two")
|
|
|
|
is.Equal(c.Counter, 2)
|
|
|
|
}
|
2023-03-19 08:31:00 -06:00
|
|
|
|
|
|
|
func TestNestedLocker(t *testing.T) {
|
|
|
|
is := is.New(t)
|
|
|
|
|
|
|
|
value := locker.New(&config{})
|
|
|
|
other := locker.New(&config{})
|
|
|
|
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
err := value.Use(ctx, func(ctx context.Context, c *config) error {
|
|
|
|
return value.Use(ctx, func(ctx context.Context, t *config) error {
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
})
|
|
|
|
is.True(errors.Is(err, locker.ErrNested))
|
|
|
|
|
|
|
|
err = value.Use(ctx, func(ctx context.Context, c *config) error {
|
|
|
|
return other.Use(ctx, func(ctx context.Context, t *config) error {
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
})
|
|
|
|
is.NoErr(err)
|
|
|
|
|
|
|
|
err = value.Use(ctx, func(ctx context.Context, c *config) error {
|
|
|
|
return other.Use(ctx, func(ctx context.Context, t *config) error {
|
|
|
|
return value.Use(ctx, func(ctx context.Context, x *config) error {
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
is.True(errors.Is(err, locker.ErrNested))
|
|
|
|
}
|