summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fs/lock/lock_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/fs/lock/lock_test.go')
-rw-r--r--pkg/sentry/fs/lock/lock_test.go1059
1 files changed, 0 insertions, 1059 deletions
diff --git a/pkg/sentry/fs/lock/lock_test.go b/pkg/sentry/fs/lock/lock_test.go
deleted file mode 100644
index ba002aeb7..000000000
--- a/pkg/sentry/fs/lock/lock_test.go
+++ /dev/null
@@ -1,1059 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package lock
-
-import (
- "reflect"
- "testing"
-)
-
-type entry struct {
- Lock
- LockRange
-}
-
-func equals(e0, e1 []entry) bool {
- if len(e0) != len(e1) {
- return false
- }
- for i := range e0 {
- for k := range e0[i].Lock.Readers {
- if !e1[i].Lock.Readers[k] {
- return false
- }
- }
- for k := range e1[i].Lock.Readers {
- if !e0[i].Lock.Readers[k] {
- return false
- }
- }
- if !reflect.DeepEqual(e0[i].LockRange, e1[i].LockRange) {
- return false
- }
- if e0[i].Lock.HasWriter != e1[i].Lock.HasWriter {
- return false
- }
- if e0[i].Lock.Writer != e1[i].Lock.Writer {
- return false
- }
- }
- return true
-}
-
-// fill a LockSet with consecutive region locks. Will panic if
-// LockRanges are not consecutive.
-func fill(entries []entry) LockSet {
- l := LockSet{}
- for _, e := range entries {
- gap := l.FindGap(e.LockRange.Start)
- if !gap.Ok() {
- panic("cannot insert into existing segment")
- }
- l.Insert(gap, e.LockRange, e.Lock)
- }
- return l
-}
-
-func TestCanLockEmpty(t *testing.T) {
- l := LockSet{}
-
- // Expect to be able to take any locks given that the set is empty.
- eof := l.FirstGap().End()
- r := LockRange{0, eof}
- if !l.canLock(1, ReadLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", ReadLock, r, 1)
- }
- if !l.canLock(2, ReadLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", ReadLock, r, 2)
- }
- if !l.canLock(1, WriteLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", WriteLock, r, 1)
- }
- if !l.canLock(2, WriteLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", WriteLock, r, 2)
- }
-}
-
-func TestCanLock(t *testing.T) {
- // + -------------- + ---------- + -------------- + --------- +
- // | Readers 1 & 2 | Readers 1 | Readers 1 & 3 | Writer 1 |
- // + ------------- + ---------- + -------------- + --------- +
- // 0 1024 2048 3072 4096
- l := fill([]entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{1: true, 2: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{1: true}},
- LockRange: LockRange{1024, 2048},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{1: true, 3: true}},
- LockRange: LockRange{2048, 3072},
- },
- {
- Lock: Lock{HasWriter: true, Writer: 1},
- LockRange: LockRange{3072, 4096},
- },
- })
-
- // Now that we have a mildly interesting layout, try some checks on different
- // ranges, uids, and lock types.
- //
- // Expect to be able to extend the read lock, despite the writer lock, because
- // the writer has the same uid as the requested read lock.
- r := LockRange{0, 8192}
- if !l.canLock(1, ReadLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", ReadLock, r, 1)
- }
- // Expect to *not* be able to extend the read lock since there is an overlapping
- // writer region locked by someone other than the uid.
- if l.canLock(2, ReadLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got true, want false", ReadLock, r, 2)
- }
- // Expect to be able to extend the read lock if there are only other readers in
- // the way.
- r = LockRange{64, 3072}
- if !l.canLock(2, ReadLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", ReadLock, r, 2)
- }
- // Expect to be able to set a read lock beyond the range of any existing locks.
- r = LockRange{4096, 10240}
- if !l.canLock(2, ReadLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", ReadLock, r, 2)
- }
-
- // Expect to not be able to take a write lock with other readers in the way.
- r = LockRange{0, 8192}
- if l.canLock(1, WriteLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got true, want false", WriteLock, r, 1)
- }
- // Expect to be able to extend the write lock for the same uid.
- r = LockRange{3072, 8192}
- if !l.canLock(1, WriteLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", WriteLock, r, 1)
- }
- // Expect to not be able to overlap a write lock for two different uids.
- if l.canLock(2, WriteLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got true, want false", WriteLock, r, 2)
- }
- // Expect to be able to set a write lock that is beyond the range of any
- // existing locks.
- r = LockRange{8192, 10240}
- if !l.canLock(2, WriteLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", WriteLock, r, 2)
- }
- // Expect to be able to upgrade a read lock (any portion of it).
- r = LockRange{1024, 2048}
- if !l.canLock(1, WriteLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", WriteLock, r, 1)
- }
- r = LockRange{1080, 2000}
- if !l.canLock(1, WriteLock, r) {
- t.Fatalf("canLock type %d for range %v and uid %d got false, want true", WriteLock, r, 1)
- }
-}
-
-func TestSetLock(t *testing.T) {
- tests := []struct {
- // description of test.
- name string
-
- // LockSet entries to pre-fill.
- before []entry
-
- // Description of region to lock:
- //
- // start is the file offset of the lock.
- start uint64
- // end is the end file offset of the lock.
- end uint64
- // uid of lock attempter.
- uid UniqueID
- // lock type requested.
- lockType LockType
-
- // success is true if taking the above
- // lock should succeed.
- success bool
-
- // Expected layout of the set after locking
- // if success is true.
- after []entry
- }{
- {
- name: "set zero length ReadLock on empty set",
- start: 0,
- end: 0,
- uid: 0,
- lockType: ReadLock,
- success: true,
- },
- {
- name: "set zero length WriteLock on empty set",
- start: 0,
- end: 0,
- uid: 0,
- lockType: WriteLock,
- success: true,
- },
- {
- name: "set ReadLock on empty set",
- start: 0,
- end: LockEOF,
- uid: 0,
- lockType: ReadLock,
- success: true,
- // + ----------------------------------------- +
- // | Readers 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- },
- {
- name: "set WriteLock on empty set",
- start: 0,
- end: LockEOF,
- uid: 0,
- lockType: WriteLock,
- success: true,
- // + ----------------------------------------- +
- // | Writer 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- after: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, LockEOF},
- },
- },
- },
- {
- name: "set ReadLock on WriteLock same uid",
- // + ----------------------------------------- +
- // | Writer 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 0,
- end: 4096,
- uid: 0,
- lockType: ReadLock,
- success: true,
- // + ----------- + --------------------------- +
- // | Readers 0 | Writer 0 |
- // + ----------- + --------------------------- +
- // 0 4096 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, 4096},
- },
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "set WriteLock on ReadLock same uid",
- // + ----------------------------------------- +
- // | Readers 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 0,
- end: 4096,
- uid: 0,
- lockType: WriteLock,
- success: true,
- // + ----------- + --------------------------- +
- // | Writer 0 | Readers 0 |
- // + ----------- + --------------------------- +
- // 0 4096 max uint64
- after: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, 4096},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "set ReadLock on WriteLock different uid",
- // + ----------------------------------------- +
- // | Writer 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 0,
- end: 4096,
- uid: 1,
- lockType: ReadLock,
- success: false,
- },
- {
- name: "set WriteLock on ReadLock different uid",
- // + ----------------------------------------- +
- // | Readers 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 0,
- end: 4096,
- uid: 1,
- lockType: WriteLock,
- success: false,
- },
- {
- name: "split ReadLock for overlapping lock at start 0",
- // + ----------------------------------------- +
- // | Readers 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 0,
- end: 4096,
- uid: 1,
- lockType: ReadLock,
- success: true,
- // + -------------- + --------------------------- +
- // | Readers 0 & 1 | Readers 0 |
- // + -------------- + --------------------------- +
- // 0 4096 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{0, 4096},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "split ReadLock for overlapping lock at non-zero start",
- // + ----------------------------------------- +
- // | Readers 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 4096,
- end: 8192,
- uid: 1,
- lockType: ReadLock,
- success: true,
- // + ---------- + -------------- + ----------- +
- // | Readers 0 | Readers 0 & 1 | Readers 0 |
- // + ---------- + -------------- + ----------- +
- // 0 4096 8192 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, 4096},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{4096, 8192},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{8192, LockEOF},
- },
- },
- },
- {
- name: "fill front gap with ReadLock",
- // + --------- + ---------------------------- +
- // | gap | Readers 0 |
- // + --------- + ---------------------------- +
- // 0 1024 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{1024, LockEOF},
- },
- },
- start: 0,
- end: 8192,
- uid: 0,
- lockType: ReadLock,
- success: true,
- // + ----------------------------------------- +
- // | Readers 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- },
- {
- name: "fill end gap with ReadLock",
- // + ---------------------------- +
- // | Readers 0 |
- // + ---------------------------- +
- // 0 4096
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, 4096},
- },
- },
- start: 1024,
- end: LockEOF,
- uid: 0,
- lockType: ReadLock,
- success: true,
- // Note that this is not merged after lock does a Split. This is
- // fine because the two locks will still *behave* as one. In other
- // words we can fragment any lock all we want and semantically it
- // makes no difference.
- //
- // + ----------- + --------------------------- +
- // | Readers 0 | Readers 0 |
- // + ----------- + --------------------------- +
- // 0 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{1024, LockEOF},
- },
- },
- },
- {
- name: "fill gap with ReadLock and split",
- // + --------- + ---------------------------- +
- // | gap | Readers 0 |
- // + --------- + ---------------------------- +
- // 0 1024 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{1024, LockEOF},
- },
- },
- start: 0,
- end: 4096,
- uid: 1,
- lockType: ReadLock,
- success: true,
- // + --------- + ------------- + ------------- +
- // | Reader 1 | Readers 0 & 1 | Reader 0 |
- // + ----------+ ------------- + ------------- +
- // 0 1024 4096 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{1: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{1024, 4096},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "upgrade ReadLock to WriteLock for single uid fill gap",
- // + ------------- + --------- + --- + ------------- +
- // | Readers 0 & 1 | Readers 0 | gap | Readers 0 & 2 |
- // + ------------- + --------- + --- + ------------- +
- // 0 1024 2048 4096 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{1024, 2048},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 2: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- start: 1024,
- end: 4096,
- uid: 0,
- lockType: WriteLock,
- success: true,
- // + ------------- + -------- + ------------- +
- // | Readers 0 & 1 | Writer 0 | Readers 0 & 2 |
- // + ------------- + -------- + ------------- +
- // 0 1024 4096 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{1024, 4096},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 2: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "upgrade ReadLock to WriteLock for single uid keep gap",
- // + ------------- + --------- + --- + ------------- +
- // | Readers 0 & 1 | Readers 0 | gap | Readers 0 & 2 |
- // + ------------- + --------- + --- + ------------- +
- // 0 1024 2048 4096 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{1024, 2048},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 2: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- start: 1024,
- end: 3072,
- uid: 0,
- lockType: WriteLock,
- success: true,
- // + ------------- + -------- + --- + ------------- +
- // | Readers 0 & 1 | Writer 0 | gap | Readers 0 & 2 |
- // + ------------- + -------- + --- + ------------- +
- // 0 1024 3072 4096 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{1024, 3072},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 2: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "fail to upgrade ReadLock to WriteLock with conflicting Reader",
- // + ------------- + --------- +
- // | Readers 0 & 1 | Readers 0 |
- // + ------------- + --------- +
- // 0 1024 2048
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{1024, 2048},
- },
- },
- start: 0,
- end: 2048,
- uid: 0,
- lockType: WriteLock,
- success: false,
- },
- {
- name: "take WriteLock on whole file if all uids are the same",
- // + ------------- + --------- + --------- + ---------- +
- // | Writer 0 | Readers 0 | Readers 0 | Readers 0 |
- // + ------------- + --------- + --------- + ---------- +
- // 0 1024 2048 4096 max uint64
- before: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{1024, 2048},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{2048, 4096},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- start: 0,
- end: LockEOF,
- uid: 0,
- lockType: WriteLock,
- success: true,
- // We do not manually merge locks. Semantically a fragmented lock
- // held by the same uid will behave as one lock so it makes no difference.
- //
- // + ------------- + ---------------------------- +
- // | Writer 0 | Writer 0 |
- // + ------------- + ---------------------------- +
- // 0 1024 max uint64
- after: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{1024, LockEOF},
- },
- },
- },
- }
-
- for _, test := range tests {
- l := fill(test.before)
-
- r := LockRange{Start: test.start, End: test.end}
- success := l.lock(test.uid, test.lockType, r)
- var got []entry
- for seg := l.FirstSegment(); seg.Ok(); seg = seg.NextSegment() {
- got = append(got, entry{
- Lock: seg.Value(),
- LockRange: seg.Range(),
- })
- }
-
- if success != test.success {
- t.Errorf("%s: setlock(%v, %+v, %d, %d) got success %v, want %v", test.name, test.before, r, test.uid, test.lockType, success, test.success)
- continue
- }
-
- if success {
- if !equals(got, test.after) {
- t.Errorf("%s: got set %+v, want %+v", test.name, got, test.after)
- }
- }
- }
-}
-
-func TestUnlock(t *testing.T) {
- tests := []struct {
- // description of test.
- name string
-
- // LockSet entries to pre-fill.
- before []entry
-
- // Description of region to unlock:
- //
- // start is the file start of the lock.
- start uint64
- // end is the end file start of the lock.
- end uint64
- // uid of lock holder.
- uid UniqueID
-
- // Expected layout of the set after unlocking.
- after []entry
- }{
- {
- name: "unlock zero length on empty set",
- start: 0,
- end: 0,
- uid: 0,
- },
- {
- name: "unlock on empty set (no-op)",
- start: 0,
- end: LockEOF,
- uid: 0,
- },
- {
- name: "unlock uid not locked (no-op)",
- // + --------------------------- +
- // | Readers 1 & 2 |
- // + --------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{1: true, 2: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 1024,
- end: 4096,
- uid: 0,
- // + --------------------------- +
- // | Readers 1 & 2 |
- // + --------------------------- +
- // 0 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{1: true, 2: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- },
- {
- name: "unlock ReadLock over entire file",
- // + ----------------------------------------- +
- // | Readers 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 0,
- end: LockEOF,
- uid: 0,
- },
- {
- name: "unlock WriteLock over entire file",
- // + ----------------------------------------- +
- // | Writer 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 0,
- end: LockEOF,
- uid: 0,
- },
- {
- name: "unlock partial ReadLock (start)",
- // + ----------------------------------------- +
- // | Readers 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 0,
- end: 4096,
- uid: 0,
- // + ------ + --------------------------- +
- // | gap | Readers 0 |
- // +------- + --------------------------- +
- // 0 4096 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "unlock partial WriteLock (start)",
- // + ----------------------------------------- +
- // | Writer 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 0,
- end: 4096,
- uid: 0,
- // + ------ + --------------------------- +
- // | gap | Writer 0 |
- // +------- + --------------------------- +
- // 0 4096 max uint64
- after: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "unlock partial ReadLock (end)",
- // + ----------------------------------------- +
- // | Readers 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 4096,
- end: LockEOF,
- uid: 0,
- // + --------------------------- +
- // | Readers 0 |
- // +---------------------------- +
- // 0 4096
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true}},
- LockRange: LockRange{0, 4096},
- },
- },
- },
- {
- name: "unlock partial WriteLock (end)",
- // + ----------------------------------------- +
- // | Writer 0 |
- // + ----------------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 4096,
- end: LockEOF,
- uid: 0,
- // + --------------------------- +
- // | Writer 0 |
- // +---------------------------- +
- // 0 4096
- after: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, 4096},
- },
- },
- },
- {
- name: "unlock for single uid",
- // + ------------- + --------- + ------------------- +
- // | Readers 0 & 1 | Writer 0 | Readers 0 & 1 & 2 |
- // + ------------- + --------- + ------------------- +
- // 0 1024 4096 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{1024, 4096},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true, 2: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- start: 0,
- end: LockEOF,
- uid: 0,
- // + --------- + --- + --------------- +
- // | Readers 1 | gap | Readers 1 & 2 |
- // + --------- + --- + --------------- +
- // 0 1024 4096 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{1: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{1: true, 2: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "unlock subsection locked",
- // + ------------------------------- +
- // | Readers 0 & 1 & 2 |
- // + ------------------------------- +
- // 0 max uint64
- before: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true, 2: true}},
- LockRange: LockRange{0, LockEOF},
- },
- },
- start: 1024,
- end: 4096,
- uid: 0,
- // + ----------------- + ------------- + ----------------- +
- // | Readers 0 & 1 & 2 | Readers 1 & 2 | Readers 0 & 1 & 2 |
- // + ----------------- + ------------- + ----------------- +
- // 0 1024 4096 max uint64
- after: []entry{
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true, 2: true}},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{1: true, 2: true}},
- LockRange: LockRange{1024, 4096},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true, 2: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "unlock mid-gap to increase gap",
- // + --------- + ----- + ------------------- +
- // | Writer 0 | gap | Readers 0 & 1 |
- // + --------- + ----- + ------------------- +
- // 0 1024 4096 max uint64
- before: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- start: 8,
- end: 2048,
- uid: 0,
- // + --------- + ----- + ------------------- +
- // | Writer 0 | gap | Readers 0 & 1 |
- // + --------- + ----- + ------------------- +
- // 0 8 4096 max uint64
- after: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, 8},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- },
- {
- name: "unlock split region on uid mid-gap",
- // + --------- + ----- + ------------------- +
- // | Writer 0 | gap | Readers 0 & 1 |
- // + --------- + ----- + ------------------- +
- // 0 1024 4096 max uint64
- before: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{4096, LockEOF},
- },
- },
- start: 2048,
- end: 8192,
- uid: 0,
- // + --------- + ----- + --------- + ------------- +
- // | Writer 0 | gap | Readers 1 | Readers 0 & 1 |
- // + --------- + ----- + --------- + ------------- +
- // 0 1024 4096 8192 max uint64
- after: []entry{
- {
- Lock: Lock{HasWriter: true, Writer: 0},
- LockRange: LockRange{0, 1024},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{1: true}},
- LockRange: LockRange{4096, 8192},
- },
- {
- Lock: Lock{Readers: map[UniqueID]bool{0: true, 1: true}},
- LockRange: LockRange{8192, LockEOF},
- },
- },
- },
- }
-
- for _, test := range tests {
- l := fill(test.before)
-
- r := LockRange{Start: test.start, End: test.end}
- l.unlock(test.uid, r)
- var got []entry
- for seg := l.FirstSegment(); seg.Ok(); seg = seg.NextSegment() {
- got = append(got, entry{
- Lock: seg.Value(),
- LockRange: seg.Range(),
- })
- }
- if !equals(got, test.after) {
- t.Errorf("%s: got set %+v, want %+v", test.name, got, test.after)
- }
- }
-}