/* * Copyright 2014-2017 Real Logic Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.aeron; import io.aeron.driver.MediaDriver; import org.junit.After; import org.junit.Before; import org.junit.Test; import io.aeron.driver.ThreadingMode; import io.aeron.logbuffer.FragmentHandler; import io.aeron.logbuffer.Header; import io.aeron.protocol.DataHeaderFlyweight; import org.agrona.BitUtil; import org.agrona.DirectBuffer; import org.agrona.concurrent.UnsafeBuffer; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; public class PongTest { public static final String PING_URI = "aeron:udp?endpoint=localhost:54325"; public static final String PONG_URI = "aeron:udp?endpoint=localhost:54326"; private static final int PING_STREAM_ID = 1; private static final int PONG_STREAM_ID = 2; private static final ThreadingMode THREADING_MODE = ThreadingMode.SHARED; private final MediaDriver.Context context = new MediaDriver.Context(); private final Aeron.Context pingAeronContext = new Aeron.Context(); private final Aeron.Context pongAeronContext = new Aeron.Context(); private Aeron pingClient; private Aeron pongClient; private MediaDriver driver; private Subscription pingSubscription; private Subscription pongSubscription; private Publication pingPublication; private Publication pongPublication; private UnsafeBuffer buffer = new UnsafeBuffer(new byte[4096]); private FragmentHandler pongHandler = mock(FragmentHandler.class); @Before public void setUp() throws Exception { context.threadingMode(THREADING_MODE); driver = MediaDriver.launch(context); pingClient = Aeron.connect(pingAeronContext); pongClient = Aeron.connect(pongAeronContext); pingPublication = pingClient.addPublication(PING_URI, PING_STREAM_ID); pingSubscription = pongClient.addSubscription(PING_URI, PING_STREAM_ID); pongPublication = pongClient.addPublication(PONG_URI, PONG_STREAM_ID); pongSubscription = pingClient.addSubscription(PONG_URI, PONG_STREAM_ID); } @After public void closeEverything() throws Exception { pongClient.close(); pingClient.close(); driver.close(); context.deleteAeronDirectory(); } @Test public void playPingPong() { buffer.putInt(0, 1); while (pingPublication.offer(buffer, 0, BitUtil.SIZE_OF_INT) < 0L) { Thread.yield(); } final AtomicInteger fragmentsRead = new AtomicInteger(); SystemTestHelper.executeUntil( () -> fragmentsRead.get() > 0, (i) -> { fragmentsRead.addAndGet(pingSubscription.poll(this::pingHandler, 10)); Thread.yield(); }, Integer.MAX_VALUE, TimeUnit.MILLISECONDS.toNanos(5900)); fragmentsRead.set(0); SystemTestHelper.executeUntil( () -> fragmentsRead.get() > 0, (i) -> { fragmentsRead.addAndGet(pongSubscription.poll(pongHandler, 10)); Thread.yield(); }, Integer.MAX_VALUE, TimeUnit.MILLISECONDS.toNanos(5900)); verify(pongHandler).onFragment( any(DirectBuffer.class), eq(DataHeaderFlyweight.HEADER_LENGTH), eq(BitUtil.SIZE_OF_INT), any(Header.class)); } public void pingHandler(final DirectBuffer buffer, final int offset, final int length, final Header header) { // echoes back the ping while (pongPublication.offer(buffer, offset, length) < 0L) { Thread.yield(); } } }