github.com/minio/mc@v0.0.0-20240503112107-b471de8d1882/cmd/pipechan_test.go (about)

     1  // Copyright (c) 2015-2022 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 cmd
    19  
    20  import (
    21  	"fmt"
    22  	"sync"
    23  	"testing"
    24  
    25  	"github.com/rjeczalik/notify"
    26  )
    27  
    28  func testPipeChan(inputCh, outputCh chan notify.EventInfo, totalMsgs int) error {
    29  	var wg sync.WaitGroup
    30  
    31  	msgCtnt := notify.EventInfo(nil)
    32  
    33  	// Send messages up to totalMsgs
    34  	wg.Add(1)
    35  	go func() {
    36  		defer wg.Done()
    37  		for i := 0; i < totalMsgs; i++ {
    38  			inputCh <- msgCtnt
    39  		}
    40  		close(inputCh)
    41  	}()
    42  
    43  	// Goroutine to receive and check messages
    44  	var recvMsgs int
    45  	var recvErr error
    46  
    47  	wg.Add(1)
    48  
    49  	go func() {
    50  		defer wg.Done()
    51  		for msg := range outputCh {
    52  			recvMsgs++
    53  			if msg != msgCtnt {
    54  				recvErr = fmt.Errorf("Corrupted message, expected = `%s`, found = `%s`", msgCtnt, msg)
    55  				return
    56  			}
    57  		}
    58  	}()
    59  
    60  	// Wait until we finish sending and receiving messages
    61  	wg.Wait()
    62  
    63  	if recvErr != nil {
    64  		return recvErr
    65  	}
    66  
    67  	// Check if all messages are received
    68  	if recvMsgs != totalMsgs {
    69  		return fmt.Errorf("unable to receive all messages, expected: %d, lost: %d", totalMsgs, totalMsgs-recvMsgs)
    70  	}
    71  
    72  	return nil
    73  }
    74  
    75  // Testing code
    76  
    77  func TestPipeChannel(t *testing.T) {
    78  	fastCh, slowCh := PipeChan(1000)
    79  	err := testPipeChan(fastCh, slowCh, 10*1000)
    80  	if err != nil {
    81  		t.Errorf("ERR: %v\n", err)
    82  	}
    83  }
    84  
    85  func TestRegularChannel(t *testing.T) {
    86  	ch := make(chan notify.EventInfo, 1000)
    87  	err := testPipeChan(ch, ch, 10*1000)
    88  	if err != nil {
    89  		t.Errorf("ERR: %v\n", err)
    90  	}
    91  }
    92  
    93  // Benchmark code
    94  
    95  func benchmarkRegular(b *testing.B, msgsNum int) {
    96  	for n := 0; n < b.N; n++ {
    97  		ch := make(chan notify.EventInfo, msgsNum)
    98  		testPipeChan(ch, ch, msgsNum)
    99  	}
   100  }
   101  
   102  func benchmarkPipeChan(b *testing.B, msgsNum int) {
   103  	for n := 0; n < b.N; n++ {
   104  		fastCh, slowCh := PipeChan(1000)
   105  		testPipeChan(fastCh, slowCh, msgsNum)
   106  	}
   107  }
   108  
   109  func BenchmarkRegular1M(b *testing.B) {
   110  	benchmarkRegular(b, 1*1000*1000)
   111  }
   112  
   113  func BenchmarkPipeChan1M(b *testing.B) {
   114  	benchmarkPipeChan(b, 1*1000*1000)
   115  }
   116  
   117  func BenchmarkRegular100K(b *testing.B) {
   118  	benchmarkRegular(b, 100*1000)
   119  }
   120  
   121  func BenchmarkPipeChan100K(b *testing.B) {
   122  	benchmarkPipeChan(b, 100*1000)
   123  }
   124  
   125  func BenchmarkRegular10K(b *testing.B) {
   126  	benchmarkRegular(b, 10*1000)
   127  }
   128  
   129  func BenchmarkPipeChan10K(b *testing.B) {
   130  	benchmarkPipeChan(b, 10*1000)
   131  }
   132  
   133  func BenchmarkRegular1K(b *testing.B) {
   134  	benchmarkRegular(b, 1*1000)
   135  }
   136  
   137  func BenchmarkPipeChan1K(b *testing.B) {
   138  	benchmarkPipeChan(b, 1*1000)
   139  }