X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/9828e9218084856240fdeafa2d388d8bf322e655..09cbdc3074b3f1e69c9c537875146f6da0a6ed8f:/lib/controller/dblock/dblock_test.go diff --git a/lib/controller/dblock/dblock_test.go b/lib/controller/dblock/dblock_test.go new file mode 100644 index 0000000000..b10b2a3acd --- /dev/null +++ b/lib/controller/dblock/dblock_test.go @@ -0,0 +1,91 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +package dblock + +import ( + "bytes" + "context" + "sync" + "testing" + "time" + + "git.arvados.org/arvados.git/lib/config" + "git.arvados.org/arvados.git/sdk/go/arvados" + "git.arvados.org/arvados.git/sdk/go/arvadostest" + "git.arvados.org/arvados.git/sdk/go/ctxlog" + "github.com/jmoiron/sqlx" + "github.com/sirupsen/logrus" + check "gopkg.in/check.v1" +) + +func Test(t *testing.T) { + check.TestingT(t) +} + +var _ = check.Suite(&suite{}) + +type suite struct { + cluster *arvados.Cluster + db *sqlx.DB + getdb func(context.Context) (*sqlx.DB, error) +} + +var testLocker = &DBLocker{key: 999} + +func (s *suite) SetUpSuite(c *check.C) { + cfg, err := config.NewLoader(nil, ctxlog.TestLogger(c)).Load() + c.Assert(err, check.IsNil) + s.cluster, err = cfg.GetCluster("") + c.Assert(err, check.IsNil) + s.db = arvadostest.DB(c, s.cluster) + s.getdb = func(context.Context) (*sqlx.DB, error) { return s.db, nil } +} + +func (s *suite) TestLock(c *check.C) { + retryDelay = 10 * time.Millisecond + + var logbuf bytes.Buffer + logger := ctxlog.New(&logbuf, "text", "debug") + logger.Level = logrus.DebugLevel + ctx := ctxlog.Context(context.Background(), logger) + ctx, cancel := context.WithCancel(ctx) + defer cancel() + testLocker.Lock(ctx, s.getdb) + testLocker.Check() + + lock2 := make(chan bool) + var wg sync.WaitGroup + defer wg.Wait() + wg.Add(1) + go func() { + defer wg.Done() + testLocker2 := &DBLocker{key: 999} + testLocker2.Lock(ctx, s.getdb) + close(lock2) + testLocker2.Check() + testLocker2.Unlock() + }() + + // Second lock should wait for first to Unlock + select { + case <-time.After(time.Second / 10): + c.Check(logbuf.String(), check.Matches, `(?ms).*level=info.*DBClient="[^"]+:\d+".*ID=999.*`) + case <-lock2: + c.Log("double-lock") + c.Fail() + } + + testLocker.Check() + testLocker.Unlock() + + // Now the second lock should succeed within retryDelay + select { + case <-time.After(retryDelay * 2): + c.Log("timed out") + c.Fail() + case <-lock2: + } + c.Logf("%s", logbuf.String()) +}