github.com/lirm/aeron-go@v0.0.0-20230415210743-920325491dc4/aeron/publication_test.go (about)

     1  /*
     2  Copyright 2016 Stanislav Liberman
     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  
    17  package aeron
    18  
    19  import (
    20  	"github.com/lirm/aeron-go/aeron/atomic"
    21  	"github.com/lirm/aeron-go/aeron/counters"
    22  	"github.com/lirm/aeron-go/aeron/driver"
    23  	"github.com/lirm/aeron-go/aeron/logbuffer"
    24  	"github.com/lirm/aeron-go/aeron/ringbuffer"
    25  	"github.com/lirm/aeron-go/aeron/util"
    26  	"github.com/lirm/aeron-go/aeron/util/memmap"
    27  	"github.com/stretchr/testify/assert"
    28  	"github.com/stretchr/testify/require"
    29  	"os"
    30  	"testing"
    31  	"time"
    32  )
    33  
    34  func prepareCnc(t *testing.T) (string, *counters.MetaDataFlyweight) {
    35  	counterFileName := "cnc.dat"
    36  	mmap, err := memmap.NewFile(counterFileName, 0, 256*1024)
    37  	require.NoError(t, err)
    38  
    39  	cncBuffer := atomic.MakeBuffer(mmap.GetMemoryPtr(), mmap.GetMemorySize())
    40  	meta := counters.InitAndWrapMetaData(cncBuffer, 0, 1024, 1024, 0, 0, 0)
    41  
    42  	t.Logf("meta data: %v", meta)
    43  
    44  	return counterFileName, meta
    45  }
    46  
    47  func TestNumberOfZeros(t *testing.T) {
    48  	assert.EqualValues(t, util.NumberOfTrailingZeroes(65536), 16)
    49  	assert.EqualValues(t, util.NumberOfTrailingZeroes(131072), 17)
    50  	assert.EqualValues(t, util.NumberOfTrailingZeroes(4194304), 22)
    51  }
    52  
    53  func TestNewPublication(t *testing.T) {
    54  	cncName, meta := prepareCnc(t)
    55  	defer require.NoError(t, os.Remove(cncName))
    56  
    57  	var proxy driver.Proxy
    58  	var rb rb.ManyToOne
    59  	buf := meta.ToDriverBuf.Get()
    60  	require.NotNil(t, buf)
    61  
    62  	t.Logf("RingBuffer backing atomic.Buffer: %v", buf)
    63  	rb.Init(buf)
    64  	proxy.Init(&rb)
    65  
    66  	var cc ClientConductor
    67  	cc.Init(&proxy, nil, time.Millisecond*100, time.Millisecond*100, time.Millisecond*100, time.Millisecond*100, meta)
    68  	defer require.NoError(t, cc.Close())
    69  
    70  	lb, err := logbuffer.NewTestingLogbuffer()
    71  	defer require.NoError(t, logbuffer.RemoveTestingLogbufferFile())
    72  	require.NoError(t, err)
    73  
    74  	lb.Meta().MTULen.Set(8192)
    75  
    76  	pub := NewPublication(lb)
    77  
    78  	pub.conductor = &cc
    79  	pub.channel = "aeron:ipc"
    80  	pub.regID = 1
    81  	pub.streamID = 10
    82  	pub.sessionID = 100
    83  	metaBuffer := lb.Buffer(logbuffer.PartitionCount)
    84  	if nil == metaBuffer {
    85  		t.Logf("meta: %v", metaBuffer)
    86  	}
    87  
    88  	counter := atomic.MakeBuffer(make([]byte, 256))
    89  	pub.pubLimit = NewPosition(counter, 0)
    90  	t.Logf("pub: %v", pub.pubLimit)
    91  	require.EqualValues(t, pub.pubLimit.get(), 0)
    92  
    93  	srcBuffer := atomic.MakeBuffer(make([]byte, 256))
    94  
    95  	milliEpoch := (time.Nanosecond * time.Duration(time.Now().UnixNano())) / time.Millisecond
    96  	pos := pub.Offer(srcBuffer, 0, srcBuffer.Capacity(), nil)
    97  	t.Logf("new pos: %d", pos)
    98  	assert.Equalf(t, pos, NotConnected, "Expected publication to not be connected at %d: %d", milliEpoch, pos)
    99  
   100  	//pub.metaData.TimeOfLastStatusMsg.Set(milliEpoch.Nanoseconds())
   101  	//pos = pub.Offer(srcBuffer, 0, srcBuffer.Capacity(), nil)
   102  	//t.Logf("new pos: %d", pos)
   103  	//if pos != BackPressured {
   104  	//	t.Errorf("Expected publication to be back pressured: %d", pos)
   105  	//}
   106  	//
   107  	pub.pubLimit.set(1024)
   108  	pos = pub.Offer(srcBuffer, 0, srcBuffer.Capacity(), nil)
   109  	t.Logf("new pos: %d", pos)
   110  	assert.EqualValuesf(t, pos, srcBuffer.Capacity()+logbuffer.DataFrameHeader.Length,
   111  		"Expected publication to advance to position %d", srcBuffer.Capacity()+logbuffer.DataFrameHeader.Length)
   112  }
   113  
   114  func TestPublication_Offer(t *testing.T) {
   115  	cncName, meta := prepareCnc(t)
   116  	defer require.NoError(t, os.Remove(cncName))
   117  
   118  	var proxy driver.Proxy
   119  	var rb rb.ManyToOne
   120  	buf := meta.ToDriverBuf.Get()
   121  	require.NotNil(t, buf)
   122  	t.Logf("RingBuffer backing atomic.Buffer: %v", buf)
   123  	rb.Init(buf)
   124  	proxy.Init(&rb)
   125  
   126  	var cc ClientConductor
   127  	cc.Init(&proxy, nil, time.Millisecond*100, time.Millisecond*100, time.Millisecond*100, time.Millisecond*100, meta)
   128  	defer require.NoError(t, cc.Close())
   129  
   130  	lb, err := logbuffer.NewTestingLogbuffer()
   131  	defer require.NoError(t, logbuffer.RemoveTestingLogbufferFile())
   132  	require.NoError(t, err)
   133  
   134  	lb.Meta().MTULen.Set(8192)
   135  
   136  	pub := NewPublication(lb)
   137  
   138  	pub.conductor = &cc
   139  	pub.channel = "aeron:ipc"
   140  	pub.regID = 1
   141  	pub.streamID = 10
   142  	pub.sessionID = 100
   143  	metaBuffer := lb.Buffer(logbuffer.PartitionCount)
   144  	if nil == metaBuffer {
   145  		t.Logf("meta: %v", metaBuffer)
   146  	}
   147  
   148  	counter := atomic.MakeBuffer(make([]byte, 256))
   149  	pub.pubLimit = NewPosition(counter, 0)
   150  	t.Logf("pub: %v", pub.pubLimit)
   151  	require.EqualValues(t, pub.pubLimit.get(), 0)
   152  
   153  	srcBuffer := atomic.MakeBuffer(make([]byte, 256))
   154  	//milliEpoch := (time.Nanosecond * time.Duration(time.Now().UnixNano())) / time.Millisecond
   155  	//pub.metaData.TimeOfLastStatusMsg.Set(milliEpoch.Nanoseconds())
   156  
   157  	termBufLen := lb.Buffer(0).Capacity()
   158  	t.Logf("Term buffer length: %d", termBufLen)
   159  
   160  	frameLen := int64(srcBuffer.Capacity() + logbuffer.DataFrameHeader.Length)
   161  	pub.pubLimit.set(int64(termBufLen))
   162  	for i := int64(1); i <= int64(termBufLen)/frameLen; i++ {
   163  		pos := pub.Offer(srcBuffer, 0, srcBuffer.Capacity(), nil)
   164  		//t.Logf("new pos: %d", pos)
   165  
   166  		assert.Equalf(t, pos, frameLen*i,
   167  			"Expected publication to advance to position %d (have %d)", frameLen*i, pos)
   168  	}
   169  
   170  	pos := pub.Offer(srcBuffer, 0, srcBuffer.Capacity(), nil)
   171  	t.Logf("new pos: %d", pos)
   172  	assert.Equalf(t, pos, AdminAction,
   173  		"Expected publication to trigger AdminAction (%d)", pos)
   174  }