summaryrefslogtreecommitdiffhomepage
path: root/tools/checklocks/test/basics.go
diff options
context:
space:
mode:
Diffstat (limited to 'tools/checklocks/test/basics.go')
-rw-r--r--tools/checklocks/test/basics.go145
1 files changed, 145 insertions, 0 deletions
diff --git a/tools/checklocks/test/basics.go b/tools/checklocks/test/basics.go
new file mode 100644
index 000000000..7a773171f
--- /dev/null
+++ b/tools/checklocks/test/basics.go
@@ -0,0 +1,145 @@
+// Copyright 2020 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 test
+
+import (
+ "sync"
+)
+
+func testLockedAccessValid(tc *oneGuardStruct) {
+ tc.mu.Lock()
+ tc.guardedField = 1
+ tc.mu.Unlock()
+}
+
+func testLockedAccessIgnore(tc *oneGuardStruct) {
+ tc.mu.Lock()
+ tc.unguardedField = 1
+ tc.mu.Unlock()
+}
+
+func testUnlockedAccessInvalidWrite(tc *oneGuardStruct) {
+ tc.guardedField = 2 // +checklocksfail
+}
+
+func testUnlockedAccessInvalidRead(tc *oneGuardStruct) {
+ x := tc.guardedField // +checklocksfail
+ _ = x
+}
+
+func testUnlockedAccessValid(tc *oneGuardStruct) {
+ tc.unguardedField = 2
+}
+
+func testCallValidAccess(tc *oneGuardStruct) {
+ callValidAccess(tc)
+}
+
+func callValidAccess(tc *oneGuardStruct) {
+ tc.mu.Lock()
+ tc.guardedField = 1
+ tc.mu.Unlock()
+}
+
+func testCallValueMixup(tc *oneGuardStruct) {
+ callValueMixup(tc, tc)
+}
+
+func callValueMixup(tc1, tc2 *oneGuardStruct) {
+ tc1.mu.Lock()
+ tc2.guardedField = 2 // +checklocksfail
+ tc1.mu.Unlock()
+}
+
+func testCallPreconditionsInvalid(tc *oneGuardStruct) {
+ callPreconditions(tc) // +checklocksfail
+}
+
+func testCallPreconditionsValid(tc *oneGuardStruct) {
+ tc.mu.Lock()
+ callPreconditions(tc)
+ tc.mu.Unlock()
+}
+
+// +checklocks:tc.mu
+func callPreconditions(tc *oneGuardStruct) {
+ tc.guardedField = 1
+}
+
+type nestedFieldsStruct struct {
+ mu sync.Mutex
+
+ // +checklocks:mu
+ nestedStruct struct {
+ nested1 int
+ nested2 int
+ }
+}
+
+func testNestedGuardValid(tc *nestedFieldsStruct) {
+ tc.mu.Lock()
+ tc.nestedStruct.nested1 = 1
+ tc.nestedStruct.nested2 = 2
+ tc.mu.Unlock()
+}
+
+func testNestedGuardInvalid(tc *nestedFieldsStruct) {
+ tc.nestedStruct.nested1 = 1 // +checklocksfail
+}
+
+type rwGuardStruct struct {
+ rwMu sync.RWMutex
+
+ // +checklocks:rwMu
+ guardedField int
+}
+
+func testRWValidRead(tc *rwGuardStruct) {
+ tc.rwMu.Lock()
+ tc.guardedField = 1
+ tc.rwMu.Unlock()
+}
+
+func testRWValidWrite(tc *rwGuardStruct) {
+ tc.rwMu.RLock()
+ tc.guardedField = 2
+ tc.rwMu.RUnlock()
+}
+
+func testRWInvalidWrite(tc *rwGuardStruct) {
+ tc.guardedField = 3 // +checklocksfail
+}
+
+func testRWInvalidRead(tc *rwGuardStruct) {
+ x := tc.guardedField + 3 // +checklocksfail
+ _ = x
+}
+
+func testTwoLocksDoubleGuardStructValid(tc *twoLocksDoubleGuardStruct) {
+ tc.mu.Lock()
+ tc.secondMu.Lock()
+ tc.doubleGuardedField = 1
+ tc.secondMu.Unlock()
+}
+
+func testTwoLocksDoubleGuardStructOnlyOne(tc *twoLocksDoubleGuardStruct) {
+ tc.mu.Lock()
+ tc.doubleGuardedField = 2 // +checklocksfail
+ tc.mu.Unlock()
+}
+
+func testTwoLocksDoubleGuardStructInvalid(tc *twoLocksDoubleGuardStruct) {
+ tc.doubleGuardedField = 3 // +checklocksfail:2
+}