]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/internal/atomic: add tests for And8 and Or8
authorMichael Munday <mike.munday@ibm.com>
Wed, 30 Oct 2019 12:45:33 +0000 (12:45 +0000)
committerMichael Munday <mike.munday@ibm.com>
Thu, 31 Oct 2019 09:49:57 +0000 (09:49 +0000)
Add some simple unit tests for these atomic operations. These can't
catch all the bugs that are possible with these operations but at
least they provide some coverage.

Change-Id: I94b9f451fcc9fecdb2a1448c5357b019563ad275
Reviewed-on: https://go-review.googlesource.com/c/go/+/204317
Run-TryBot: Michael Munday <mike.munday@ibm.com>
Reviewed-by: Austin Clements <austin@google.com>
src/runtime/internal/atomic/atomic_test.go

index 9e4461ce38a12a66042a3b6ca8186b3779df2c26..0c1125c55831b663f29c278fbff532a22ce8c75d 100644 (file)
@@ -103,3 +103,120 @@ func TestUnaligned64(t *testing.T) {
        shouldPanic(t, "Xchg64", func() { atomic.Xchg64(up64, 1) })
        shouldPanic(t, "Cas64", func() { atomic.Cas64(up64, 1, 2) })
 }
+
+func TestAnd8(t *testing.T) {
+       // Basic sanity check.
+       x := uint8(0xff)
+       for i := uint8(0); i < 8; i++ {
+               atomic.And8(&x, ^(1 << i))
+               if r := uint8(0xff) << (i + 1); x != r {
+                       t.Fatalf("clearing bit %#x: want %#x, got %#x", uint8(1<<i), r, x)
+               }
+       }
+
+       // Set every bit in array to 1.
+       a := make([]uint8, 1<<12)
+       for i := range a {
+               a[i] = 0xff
+       }
+
+       // Clear array bit-by-bit in different goroutines.
+       done := make(chan bool)
+       for i := 0; i < 8; i++ {
+               m := ^uint8(1 << i)
+               go func() {
+                       for i := range a {
+                               atomic.And8(&a[i], m)
+                       }
+                       done <- true
+               }()
+       }
+       for i := 0; i < 8; i++ {
+               <-done
+       }
+
+       // Check that the array has been totally cleared.
+       for i, v := range a {
+               if v != 0 {
+                       t.Fatalf("a[%v] not cleared: want %#x, got %#x", i, uint8(0), v)
+               }
+       }
+}
+
+func TestOr8(t *testing.T) {
+       // Basic sanity check.
+       x := uint8(0)
+       for i := uint8(0); i < 8; i++ {
+               atomic.Or8(&x, 1<<i)
+               if r := (uint8(1) << (i + 1)) - 1; x != r {
+                       t.Fatalf("setting bit %#x: want %#x, got %#x", uint8(1)<<i, r, x)
+               }
+       }
+
+       // Start with every bit in array set to 0.
+       a := make([]uint8, 1<<12)
+
+       // Set every bit in array bit-by-bit in different goroutines.
+       done := make(chan bool)
+       for i := 0; i < 8; i++ {
+               m := uint8(1 << i)
+               go func() {
+                       for i := range a {
+                               atomic.Or8(&a[i], m)
+                       }
+                       done <- true
+               }()
+       }
+       for i := 0; i < 8; i++ {
+               <-done
+       }
+
+       // Check that the array has been totally set.
+       for i, v := range a {
+               if v != 0xff {
+                       t.Fatalf("a[%v] not fully set: want %#x, got %#x", i, uint8(0xff), v)
+               }
+       }
+}
+
+func TestBitwiseContended(t *testing.T) {
+       // Start with every bit in array set to 0.
+       a := make([]uint8, 16)
+
+       // Iterations to try.
+       N := 1 << 16
+       if testing.Short() {
+               N = 1 << 10
+       }
+
+       // Set and then clear every bit in the array bit-by-bit in different goroutines.
+       done := make(chan bool)
+       for i := 0; i < 8; i++ {
+               m := uint8(1 << i)
+               go func() {
+                       for n := 0; n < N; n++ {
+                               for i := range a {
+                                       atomic.Or8(&a[i], m)
+                                       if atomic.Load8(&a[i])&m != m {
+                                               t.Errorf("a[%v] bit %#x not set", i, m)
+                                       }
+                                       atomic.And8(&a[i], ^m)
+                                       if atomic.Load8(&a[i])&m != 0 {
+                                               t.Errorf("a[%v] bit %#x not clear", i, m)
+                                       }
+                               }
+                       }
+                       done <- true
+               }()
+       }
+       for i := 0; i < 8; i++ {
+               <-done
+       }
+
+       // Check that the array has been totally cleared.
+       for i, v := range a {
+               if v != 0 {
+                       t.Fatalf("a[%v] not cleared: want %#x, got %#x", i, uint8(0), v)
+               }
+       }
+}