bitbucket.org/ai69/amoy@v0.2.3/channel_test.go (about)

     1  package amoy
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/1set/gut/yhash"
     9  	"github.com/1set/gut/yrand"
    10  )
    11  
    12  func BenchmarkAccumulatedChannel(b *testing.B) {
    13  	var (
    14  		dataSize  = 2048
    15  		bufSize   = 500
    16  		chunkSize = 128
    17  	)
    18  	rawStr, _ := yrand.StringBase62(dataSize)
    19  	rawBytes := []byte(rawStr)
    20  
    21  	b.ResetTimer()
    22  	for i := 0; i < b.N; i++ {
    23  		inCh := make(chan []byte)
    24  		outCh := AccumulatedChannel(inCh, bufSize)
    25  		done := make(chan struct{})
    26  		go func() {
    27  			for range outCh {
    28  				//revive:disable:empty-block
    29  				// yes, it's empty
    30  			}
    31  			close(done)
    32  		}()
    33  		fillChannelRandomChunk(inCh, rawBytes, chunkSize, chunkSize)
    34  		close(inCh)
    35  		<-done
    36  	}
    37  }
    38  
    39  func TestAccumulatedChannel(t *testing.T) {
    40  	tests := []struct {
    41  		dataSize  int
    42  		batchSize int
    43  		minSize   int
    44  		maxSize   int
    45  	}{
    46  		{0, 1, 1, 1},
    47  		{1, 1, 1, 1},
    48  		{1024, 1, 1, 1},
    49  		{1024, 10, 2, 2},
    50  		{1024, 10, 2, 5},
    51  		{1024, 1024, 2, 5},
    52  		{1024, 1025, 2, 5},
    53  		{1024, 10, 1024, 1024},
    54  		{1024, 1024, 1024, 1024},
    55  		{1024, 10, 2048, 2048},
    56  	}
    57  	for _, tt := range tests {
    58  		name := fmt.Sprintf("%d->(%d,%d-%d)", tt.dataSize, tt.batchSize, tt.minSize, tt.maxSize)
    59  		t.Run(name, func(t *testing.T) {
    60  			var (
    61  				rawBytes []byte
    62  				cumBytes []byte
    63  			)
    64  			rawStr, _ := yrand.StringBase62(tt.dataSize)
    65  			if len(rawStr) > 0 {
    66  				rawBytes = []byte(rawStr)
    67  			}
    68  
    69  			inCh := make(chan []byte)
    70  			outCh := AccumulatedChannel(inCh, tt.batchSize)
    71  			done := make(chan struct{})
    72  			go func() {
    73  				for v := range outCh {
    74  					cumBytes = append(cumBytes, v...)
    75  				}
    76  				close(done)
    77  			}()
    78  			fillChannelRandomChunk(inCh, rawBytes, tt.minSize, tt.maxSize)
    79  			close(inCh)
    80  			<-done
    81  
    82  			if !reflect.DeepEqual(rawBytes, cumBytes) {
    83  				rh, _ := yhash.BytesMD5(rawBytes)
    84  				ch, _ := yhash.BytesMD5(cumBytes)
    85  				t.Errorf("AccumulatedChannel([%d]%v) != [%d]%v breaks data", len(rawBytes), rh, len(cumBytes), ch)
    86  			}
    87  		})
    88  	}
    89  }
    90  
    91  func TestBlockForever(t *testing.T) {
    92  	go func() {
    93  		BlockForever()
    94  		t.Errorf("BlockForever() should not return")
    95  	}()
    96  	SleepForMilliseconds(10)
    97  }
    98  
    99  // fillChannelRandomChunk fills the channel with given data in random chunk sizes (min <= size < max).
   100  func fillChannelRandomChunk(in chan []byte, data []byte, min, max int) {
   101  	var pos int
   102  	for {
   103  		l := min
   104  		if min < max {
   105  			l, _ = yrand.IntRange(min, max)
   106  		}
   107  		if l == 0 {
   108  			in <- []byte{}
   109  			continue
   110  		}
   111  		if pos+l > len(data) {
   112  			l = len(data) - pos
   113  		}
   114  		in <- data[pos : pos+l]
   115  		pos += l
   116  		if pos >= len(data) {
   117  			break
   118  		}
   119  	}
   120  }