github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/internal/store/batch_test.go (about)

     1  // Copyright (c) 2023 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package store
    19  
    20  import (
    21  	"errors"
    22  	"sync"
    23  	"testing"
    24  )
    25  
    26  func TestBatch(t *testing.T) {
    27  	var limit uint32 = 100
    28  	batch := NewBatch[int, int](limit)
    29  	for i := 0; i < int(limit); i++ {
    30  		if err := batch.Add(i, i); err != nil {
    31  			t.Fatalf("failed to add %v; %v", i, err)
    32  		}
    33  		if _, ok := batch.GetByKey(i); !ok {
    34  			t.Fatalf("failed to get the item by key %v after adding", i)
    35  		}
    36  	}
    37  	err := batch.Add(101, 101)
    38  	if err == nil || !errors.Is(err, ErrBatchFull) {
    39  		t.Fatalf("Expected err %v but got %v", ErrBatchFull, err)
    40  	}
    41  	if !batch.IsFull() {
    42  		t.Fatal("Expected batch.IsFull to be true but got false")
    43  	}
    44  	batchLen := batch.Len()
    45  	if batchLen != int(limit) {
    46  		t.Fatalf("expected batch length to be %v but got %v", limit, batchLen)
    47  	}
    48  	keys, items, err := batch.GetAll()
    49  	if err != nil {
    50  		t.Fatalf("unable to get the items from the batch; %v", err)
    51  	}
    52  	if len(items) != int(limit) {
    53  		t.Fatalf("Expected length of the batch items to be %v but got %v", limit, len(items))
    54  	}
    55  	if len(keys) != int(limit) {
    56  		t.Fatalf("Expected length of the batch keys to be %v but got %v", limit, len(items))
    57  	}
    58  	batchLen = batch.Len()
    59  	if batchLen != 0 {
    60  		t.Fatalf("expected batch to be empty but still left with %d items", batchLen)
    61  	}
    62  	// Add duplicate entries
    63  	for i := 0; i < 10; i++ {
    64  		if err := batch.Add(99, 99); err != nil {
    65  			t.Fatalf("failed to add duplicate item %v to batch after Get; %v", i, err)
    66  		}
    67  	}
    68  	if _, ok := batch.GetByKey(99); !ok {
    69  		t.Fatal("failed to get the duplicxate item by key '99' after adding")
    70  	}
    71  	keys, items, err = batch.GetAll()
    72  	if err != nil {
    73  		t.Fatalf("unable to get the items from the batch; %v", err)
    74  	}
    75  	if len(items) != 1 {
    76  		t.Fatalf("Expected length of the batch items to be 1 but got %v", len(items))
    77  	}
    78  	if len(keys) != 1 {
    79  		t.Fatalf("Expected length of the batch keys to be 1 but got %v", len(items))
    80  	}
    81  	// try adding again after Get.
    82  	for i := 0; i < int(limit); i++ {
    83  		if err := batch.Add(i, i); err != nil {
    84  			t.Fatalf("failed to add item %v to batch after Get; %v", i, err)
    85  		}
    86  		if _, ok := batch.GetByKey(i); !ok {
    87  			t.Fatalf("failed to get the item by key %v after adding", i)
    88  		}
    89  	}
    90  }
    91  
    92  func TestBatchWithConcurrency(t *testing.T) {
    93  	var limit uint32 = 100
    94  	batch := NewBatch[int, int](limit)
    95  
    96  	var wg sync.WaitGroup
    97  	for i := 0; i < int(limit); i++ {
    98  		wg.Add(1)
    99  		go func(item int) {
   100  			defer wg.Done()
   101  			if err := batch.Add(item, item); err != nil {
   102  				t.Errorf("failed to add item %v; %v", item, err)
   103  				return
   104  			}
   105  			if _, ok := batch.GetByKey(item); !ok {
   106  				t.Errorf("failed to get the item by key %v after adding", item)
   107  			}
   108  		}(i)
   109  	}
   110  	wg.Wait()
   111  
   112  	keys, items, err := batch.GetAll()
   113  	if err != nil {
   114  		t.Fatalf("unable to get the items from the batch; %v", err)
   115  	}
   116  	if len(items) != int(limit) {
   117  		t.Fatalf("expected batch length %v but got %v", limit, len(items))
   118  	}
   119  	if len(keys) != int(limit) {
   120  		t.Fatalf("Expected length of the batch keys to be %v but got %v", limit, len(items))
   121  	}
   122  	batchLen := batch.Len()
   123  	if batchLen != 0 {
   124  		t.Fatalf("expected batch to be empty but still left with %d items", batchLen)
   125  	}
   126  }