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 }