go.etcd.io/etcd@v3.3.27+incompatible/mvcc/backend/batch_tx_test.go (about)

     1  // Copyright 2015 The etcd Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package backend
    16  
    17  import (
    18  	"reflect"
    19  	"testing"
    20  	"time"
    21  
    22  	bolt "github.com/coreos/bbolt"
    23  )
    24  
    25  func TestBatchTxPut(t *testing.T) {
    26  	b, tmpPath := NewTmpBackend(time.Hour, 10000)
    27  	defer cleanup(b, tmpPath)
    28  
    29  	tx := b.batchTx
    30  	tx.Lock()
    31  	defer tx.Unlock()
    32  
    33  	// create bucket
    34  	tx.UnsafeCreateBucket([]byte("test"))
    35  
    36  	// put
    37  	v := []byte("bar")
    38  	tx.UnsafePut([]byte("test"), []byte("foo"), v)
    39  
    40  	// check put result before and after tx is committed
    41  	for k := 0; k < 2; k++ {
    42  		_, gv := tx.UnsafeRange([]byte("test"), []byte("foo"), nil, 0)
    43  		if !reflect.DeepEqual(gv[0], v) {
    44  			t.Errorf("v = %s, want %s", string(gv[0]), string(v))
    45  		}
    46  		tx.commit(false)
    47  	}
    48  }
    49  
    50  func TestBatchTxRange(t *testing.T) {
    51  	b, tmpPath := NewTmpBackend(time.Hour, 10000)
    52  	defer cleanup(b, tmpPath)
    53  
    54  	tx := b.batchTx
    55  	tx.Lock()
    56  	defer tx.Unlock()
    57  
    58  	tx.UnsafeCreateBucket([]byte("test"))
    59  	// put keys
    60  	allKeys := [][]byte{[]byte("foo"), []byte("foo1"), []byte("foo2")}
    61  	allVals := [][]byte{[]byte("bar"), []byte("bar1"), []byte("bar2")}
    62  	for i := range allKeys {
    63  		tx.UnsafePut([]byte("test"), allKeys[i], allVals[i])
    64  	}
    65  
    66  	tests := []struct {
    67  		key    []byte
    68  		endKey []byte
    69  		limit  int64
    70  
    71  		wkeys [][]byte
    72  		wvals [][]byte
    73  	}{
    74  		// single key
    75  		{
    76  			[]byte("foo"), nil, 0,
    77  			allKeys[:1], allVals[:1],
    78  		},
    79  		// single key, bad
    80  		{
    81  			[]byte("doo"), nil, 0,
    82  			nil, nil,
    83  		},
    84  		// key range
    85  		{
    86  			[]byte("foo"), []byte("foo1"), 0,
    87  			allKeys[:1], allVals[:1],
    88  		},
    89  		// key range, get all keys
    90  		{
    91  			[]byte("foo"), []byte("foo3"), 0,
    92  			allKeys, allVals,
    93  		},
    94  		// key range, bad
    95  		{
    96  			[]byte("goo"), []byte("goo3"), 0,
    97  			nil, nil,
    98  		},
    99  		// key range with effective limit
   100  		{
   101  			[]byte("foo"), []byte("foo3"), 1,
   102  			allKeys[:1], allVals[:1],
   103  		},
   104  		// key range with limit
   105  		{
   106  			[]byte("foo"), []byte("foo3"), 4,
   107  			allKeys, allVals,
   108  		},
   109  	}
   110  	for i, tt := range tests {
   111  		keys, vals := tx.UnsafeRange([]byte("test"), tt.key, tt.endKey, tt.limit)
   112  		if !reflect.DeepEqual(keys, tt.wkeys) {
   113  			t.Errorf("#%d: keys = %+v, want %+v", i, keys, tt.wkeys)
   114  		}
   115  		if !reflect.DeepEqual(vals, tt.wvals) {
   116  			t.Errorf("#%d: vals = %+v, want %+v", i, vals, tt.wvals)
   117  		}
   118  	}
   119  }
   120  
   121  func TestBatchTxDelete(t *testing.T) {
   122  	b, tmpPath := NewTmpBackend(time.Hour, 10000)
   123  	defer cleanup(b, tmpPath)
   124  
   125  	tx := b.batchTx
   126  	tx.Lock()
   127  	defer tx.Unlock()
   128  
   129  	tx.UnsafeCreateBucket([]byte("test"))
   130  	tx.UnsafePut([]byte("test"), []byte("foo"), []byte("bar"))
   131  
   132  	tx.UnsafeDelete([]byte("test"), []byte("foo"))
   133  
   134  	// check put result before and after tx is committed
   135  	for k := 0; k < 2; k++ {
   136  		ks, _ := tx.UnsafeRange([]byte("test"), []byte("foo"), nil, 0)
   137  		if len(ks) != 0 {
   138  			t.Errorf("keys on foo = %v, want nil", ks)
   139  		}
   140  		tx.commit(false)
   141  	}
   142  }
   143  
   144  func TestBatchTxCommit(t *testing.T) {
   145  	b, tmpPath := NewTmpBackend(time.Hour, 10000)
   146  	defer cleanup(b, tmpPath)
   147  
   148  	tx := b.batchTx
   149  	tx.Lock()
   150  	tx.UnsafeCreateBucket([]byte("test"))
   151  	tx.UnsafePut([]byte("test"), []byte("foo"), []byte("bar"))
   152  	tx.Unlock()
   153  
   154  	tx.Commit()
   155  
   156  	// check whether put happens via db view
   157  	b.db.View(func(tx *bolt.Tx) error {
   158  		bucket := tx.Bucket([]byte("test"))
   159  		if bucket == nil {
   160  			t.Errorf("bucket test does not exit")
   161  			return nil
   162  		}
   163  		v := bucket.Get([]byte("foo"))
   164  		if v == nil {
   165  			t.Errorf("foo key failed to written in backend")
   166  		}
   167  		return nil
   168  	})
   169  }
   170  
   171  func TestBatchTxBatchLimitCommit(t *testing.T) {
   172  	// start backend with batch limit 1 so one write can
   173  	// trigger a commit
   174  	b, tmpPath := NewTmpBackend(time.Hour, 1)
   175  	defer cleanup(b, tmpPath)
   176  
   177  	tx := b.batchTx
   178  	tx.Lock()
   179  	tx.UnsafeCreateBucket([]byte("test"))
   180  	tx.UnsafePut([]byte("test"), []byte("foo"), []byte("bar"))
   181  	tx.Unlock()
   182  
   183  	// batch limit commit should have been triggered
   184  	// check whether put happens via db view
   185  	b.db.View(func(tx *bolt.Tx) error {
   186  		bucket := tx.Bucket([]byte("test"))
   187  		if bucket == nil {
   188  			t.Errorf("bucket test does not exit")
   189  			return nil
   190  		}
   191  		v := bucket.Get([]byte("foo"))
   192  		if v == nil {
   193  			t.Errorf("foo key failed to written in backend")
   194  		}
   195  		return nil
   196  	})
   197  }