| // Copyright 2019 The gVisor Authors. |
| // |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package sync |
| |
| import ( |
| "reflect" |
| "testing" |
| "time" |
| ) |
| |
| func TestSeqCountWriteUncontended(t *testing.T) { |
| var seq SeqCount |
| seq.BeginWrite() |
| seq.EndWrite() |
| } |
| |
| func TestSeqCountReadUncontended(t *testing.T) { |
| var seq SeqCount |
| epoch := seq.BeginRead() |
| if !seq.ReadOk(epoch) { |
| t.Errorf("ReadOk: got false, wanted true") |
| } |
| } |
| |
| func TestSeqCountBeginReadAfterWrite(t *testing.T) { |
| var seq SeqCount |
| var data int32 |
| const want = 1 |
| seq.BeginWrite() |
| data = want |
| seq.EndWrite() |
| epoch := seq.BeginRead() |
| if data != want { |
| t.Errorf("Reader: got %v, wanted %v", data, want) |
| } |
| if !seq.ReadOk(epoch) { |
| t.Errorf("ReadOk: got false, wanted true") |
| } |
| } |
| |
| func TestSeqCountBeginReadDuringWrite(t *testing.T) { |
| var seq SeqCount |
| var data int |
| const want = 1 |
| seq.BeginWrite() |
| go func() { |
| time.Sleep(time.Second) |
| data = want |
| seq.EndWrite() |
| }() |
| epoch := seq.BeginRead() |
| if data != want { |
| t.Errorf("Reader: got %v, wanted %v", data, want) |
| } |
| if !seq.ReadOk(epoch) { |
| t.Errorf("ReadOk: got false, wanted true") |
| } |
| } |
| |
| func TestSeqCountReadOkAfterWrite(t *testing.T) { |
| var seq SeqCount |
| epoch := seq.BeginRead() |
| seq.BeginWrite() |
| seq.EndWrite() |
| if seq.ReadOk(epoch) { |
| t.Errorf("ReadOk: got true, wanted false") |
| } |
| } |
| |
| func TestSeqCountReadOkDuringWrite(t *testing.T) { |
| var seq SeqCount |
| epoch := seq.BeginRead() |
| seq.BeginWrite() |
| if seq.ReadOk(epoch) { |
| t.Errorf("ReadOk: got true, wanted false") |
| } |
| seq.EndWrite() |
| } |
| |
| func BenchmarkSeqCountWriteUncontended(b *testing.B) { |
| var seq SeqCount |
| for i := 0; i < b.N; i++ { |
| seq.BeginWrite() |
| seq.EndWrite() |
| } |
| } |
| |
| func BenchmarkSeqCountReadUncontended(b *testing.B) { |
| var seq SeqCount |
| b.RunParallel(func(pb *testing.PB) { |
| for pb.Next() { |
| epoch := seq.BeginRead() |
| if !seq.ReadOk(epoch) { |
| b.Fatalf("ReadOk: got false, wanted true") |
| } |
| } |
| }) |
| } |
| |
| func TestPointersInType(t *testing.T) { |
| for _, test := range []struct { |
| name string // used for both test and value name |
| val interface{} |
| ptrs []string |
| }{ |
| { |
| name: "EmptyStruct", |
| val: struct{}{}, |
| }, |
| { |
| name: "Int", |
| val: int(0), |
| }, |
| { |
| name: "MixedStruct", |
| val: struct { |
| b bool |
| I int |
| ExportedPtr *struct{} |
| unexportedPtr *struct{} |
| arr [2]int |
| ptrArr [2]*int |
| nestedStruct struct { |
| nestedNonptr int |
| nestedPtr *int |
| } |
| structArr [1]struct { |
| nonptr int |
| ptr *int |
| } |
| }{}, |
| ptrs: []string{ |
| "MixedStruct.ExportedPtr", |
| "MixedStruct.unexportedPtr", |
| "MixedStruct.ptrArr[]", |
| "MixedStruct.nestedStruct.nestedPtr", |
| "MixedStruct.structArr[].ptr", |
| }, |
| }, |
| } { |
| t.Run(test.name, func(t *testing.T) { |
| typ := reflect.TypeOf(test.val) |
| ptrs := PointersInType(typ, test.name) |
| t.Logf("Found pointers: %v", ptrs) |
| if (len(ptrs) != 0 || len(test.ptrs) != 0) && !reflect.DeepEqual(ptrs, test.ptrs) { |
| t.Errorf("Got %v, wanted %v", ptrs, test.ptrs) |
| } |
| }) |
| } |
| } |