github.com/braveheart12/just@v0.8.7/ledger/storage/lock_test.go (about)

     1  /*
     2   *    Copyright 2019 Insolar Technologies
     3   *
     4   *    Licensed under the Apache License, Version 2.0 (the "License");
     5   *    you may not use this file except in compliance with the License.
     6   *    You may obtain a copy of the License at
     7   *
     8   *        http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   *    Unless required by applicable law or agreed to in writing, software
    11   *    distributed under the License is distributed on an "AS IS" BASIS,
    12   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   *    See the License for the specific language governing permissions and
    14   *    limitations under the License.
    15   */
    16  package storage
    17  
    18  import (
    19  	"fmt"
    20  	"strings"
    21  	"sync"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/insolar/insolar/core"
    26  	"github.com/stretchr/testify/assert"
    27  )
    28  
    29  func Test_IDLockTheSame(t *testing.T) {
    30  	tl := newtestlocker()
    31  	id1 := core.RecordID{0x0A}
    32  	id2 := core.RecordID{0x0A}
    33  	start1 := make(chan bool)
    34  	start2 := make(chan bool)
    35  	var wg sync.WaitGroup
    36  	wg.Add(2)
    37  	go func() {
    38  		<-start1
    39  		tl.Lock("lock1", &id1)
    40  		close(start2)
    41  
    42  		time.Sleep(time.Millisecond * 50)
    43  		tl.Unlock("unlock1", &id1)
    44  		wg.Done()
    45  	}()
    46  	go func() {
    47  		<-start2
    48  		tl.Lock("lock2", &id2)
    49  		tl.Unlock("unlock2", &id2)
    50  		wg.Done()
    51  	}()
    52  	close(start1)
    53  	wg.Wait()
    54  
    55  	expectsteps := []string{
    56  		"before-lock1",
    57  		"before-lock2",
    58  		"before-unlock1",
    59  		"before-unlock2",
    60  	}
    61  	assert.Equal(t, expectsteps, tl.synclist.list, "steps in proper order")
    62  }
    63  
    64  func Test_IDLockDifferent(t *testing.T) {
    65  	tl := newtestlocker()
    66  	id1 := core.NewRecordID(0, []byte{0x0A})
    67  	id2 := core.NewRecordID(1, []byte{0x0A})
    68  	end := make(chan bool)
    69  	go func() {
    70  		tl.Lock("lock1", id1)
    71  		tl.Lock("lock2", id2)
    72  		tl.Unlock("unlock1", id1)
    73  		tl.Unlock("unlock2", id2)
    74  		close(end)
    75  	}()
    76  	select {
    77  	case <-end:
    78  	case <-time.After(500 * time.Millisecond):
    79  		t.Fatal("Got deadlock. Different record.ID should not lock each other.")
    80  	}
    81  
    82  	expectsteps := []string{
    83  		"before-lock1",
    84  		"before-lock2",
    85  		"before-unlock1",
    86  		"before-unlock2",
    87  	}
    88  	assert.Equal(t, expectsteps, tl.synclist.list, "steps in proper order")
    89  }
    90  
    91  // test helpers
    92  
    93  type synclist struct {
    94  	sync.Mutex
    95  	list []string
    96  }
    97  
    98  type testlock struct {
    99  	lock     *IDLocker
   100  	synclist *synclist
   101  }
   102  
   103  func newtestlocker() *testlock {
   104  	return &testlock{
   105  		lock:     NewIDLocker(),
   106  		synclist: &synclist{list: []string{}},
   107  	}
   108  }
   109  
   110  func (l *synclist) Add(name string) {
   111  	l.Lock()
   112  	l.list = append(l.list, name)
   113  	l.Unlock()
   114  }
   115  
   116  func (l *synclist) String() string {
   117  	s := []string{"Steps:"}
   118  	for n, step := range l.list {
   119  		s = append(s, fmt.Sprintf("  %v: %v", n, step))
   120  	}
   121  	return strings.Join(s, "\n")
   122  }
   123  
   124  func (tl *testlock) Lock(name string, id *core.RecordID) {
   125  	tl.synclist.Add("before-" + name)
   126  	tl.lock.Lock(id)
   127  }
   128  
   129  func (tl *testlock) Unlock(name string, id *core.RecordID) {
   130  	tl.synclist.Add("before-" + name)
   131  	tl.lock.Unlock(id)
   132  }