/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 com.twitter.distributedlog.service; import com.twitter.distributedlog.AsyncLogReader; import com.twitter.distributedlog.DLMTestUtil; import com.twitter.distributedlog.DLSN; import com.twitter.distributedlog.DistributedLogManager; import com.twitter.distributedlog.TestZooKeeperClientBuilder; import com.twitter.distributedlog.annotations.DistributedLogAnnotations; import com.twitter.distributedlog.exceptions.LogNotFoundException; import com.twitter.distributedlog.LogReader; import com.twitter.distributedlog.LogRecord; import com.twitter.distributedlog.LogRecordWithDLSN; import com.twitter.distributedlog.ZooKeeperClient; import com.twitter.distributedlog.acl.AccessControlManager; import com.twitter.distributedlog.acl.ZKAccessControl; import com.twitter.distributedlog.client.DistributedLogClientImpl; import com.twitter.distributedlog.client.routing.LocalRoutingService; import com.twitter.distributedlog.exceptions.DLException; import com.twitter.distributedlog.metadata.BKDLConfig; import com.twitter.distributedlog.namespace.DistributedLogNamespace; import com.twitter.distributedlog.service.stream.StreamManagerImpl; import com.twitter.distributedlog.thrift.AccessControlEntry; import com.twitter.distributedlog.thrift.service.BulkWriteResponse; import com.twitter.distributedlog.thrift.service.HeartbeatOptions; import com.twitter.distributedlog.thrift.service.StatusCode; import com.twitter.distributedlog.thrift.service.WriteContext; import com.twitter.distributedlog.util.FailpointUtils; import com.twitter.distributedlog.util.FutureUtils; import com.twitter.finagle.NoBrokersAvailableException; import com.twitter.finagle.builder.ClientBuilder; import com.twitter.finagle.thrift.ClientId$; import com.twitter.util.Await; import com.twitter.util.Duration; import com.twitter.util.Future; import com.twitter.util.Futures; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static com.google.common.base.Charsets.UTF_8; import static com.twitter.distributedlog.LogRecord.MAX_LOGRECORD_SIZE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; public class TestDistributedLogServer extends DistributedLogServerTestCase { static final Logger logger = LoggerFactory.getLogger(TestDistributedLogServer.class); @Rule public TestName testName = new TestName(); /** * {@link https://issues.apache.org/jira/browse/DL-27} */ @DistributedLogAnnotations.FlakyTest @Ignore @Test(timeout = 60000) public void testBasicWrite() throws Exception { String name = "dlserver-basic-write"; dlClient.routingService.addHost(name, dlServer.getAddress()); for (long i = 1; i <= 10; i++) { logger.debug("Write entry {} to stream {}.", i, name); Await.result(dlClient.dlClient.write(name, ByteBuffer.wrap(("" + i).getBytes()))); } HeartbeatOptions hbOptions = new HeartbeatOptions(); hbOptions.setSendHeartBeatToReader(true); // make sure the first log segment of each stream created FutureUtils.result(dlClient.dlClient.heartbeat(name)); DistributedLogManager dlm = DLMTestUtil.createNewDLM(name, conf, getUri()); LogReader reader = dlm.getInputStream(1); int numRead = 0; LogRecord r = reader.readNext(false); while (null != r) { int i = Integer.parseInt(new String(r.getPayload())); assertEquals(numRead + 1, i); ++numRead; r = reader.readNext(false); } assertEquals(10, numRead); reader.close(); dlm.close(); } /** * Sanity check to make sure both checksum flag values work. */ @Test(timeout = 60000) public void testChecksumFlag() throws Exception { String name = "dlserver-basic-write"; LocalRoutingService routingService = LocalRoutingService.newBuilder().build(); routingService.addHost(name, dlServer.getAddress()); DistributedLogClientBuilder dlClientBuilder = DistributedLogClientBuilder.newBuilder() .name(name) .clientId(ClientId$.MODULE$.apply("test")) .routingService(routingService) .handshakeWithClientInfo(true) .clientBuilder(ClientBuilder.get() .hostConnectionLimit(1) .connectionTimeout(Duration.fromSeconds(1)) .requestTimeout(Duration.fromSeconds(60))) .checksum(false); DistributedLogClient dlClient = (DistributedLogClientImpl) dlClientBuilder.build(); Await.result(dlClient.write(name, ByteBuffer.wrap(("1").getBytes()))); dlClient.close(); dlClient = dlClientBuilder.checksum(true).build(); Await.result(dlClient.write(name, ByteBuffer.wrap(("2").getBytes()))); dlClient.close(); } private void runSimpleBulkWriteTest(int writeCount) throws Exception { String name = String.format("dlserver-bulk-write-%d", writeCount); dlClient.routingService.addHost(name, dlServer.getAddress()); List<ByteBuffer> writes = new ArrayList<ByteBuffer>(writeCount); for (long i = 1; i <= writeCount; i++) { writes.add(ByteBuffer.wrap(("" + i).getBytes())); } logger.debug("Write {} entries to stream {}.", writeCount, name); List<Future<DLSN>> futures = dlClient.dlClient.writeBulk(name, writes); assertEquals(futures.size(), writeCount); for (Future<DLSN> future : futures) { // No throw == pass. DLSN dlsn = Await.result(future, Duration.fromSeconds(10)); } DistributedLogManager dlm = DLMTestUtil.createNewDLM(name, conf, getUri()); LogReader reader = dlm.getInputStream(1); int numRead = 0; LogRecord r = reader.readNext(false); while (null != r) { int i = Integer.parseInt(new String(r.getPayload())); assertEquals(numRead + 1, i); ++numRead; r = reader.readNext(false); } assertEquals(writeCount, numRead); reader.close(); dlm.close(); } @Test(timeout = 60000) public void testBulkWrite() throws Exception { runSimpleBulkWriteTest(100); } @Test(timeout = 60000) public void testBulkWriteSingleWrite() throws Exception { runSimpleBulkWriteTest(1); } @Test(timeout = 60000) public void testBulkWriteEmptyList() throws Exception { String name = String.format("dlserver-bulk-write-%d", 0); dlClient.routingService.addHost(name, dlServer.getAddress()); List<ByteBuffer> writes = new ArrayList<ByteBuffer>(); List<Future<DLSN>> futures = dlClient.dlClient.writeBulk(name, writes); assertEquals(0, futures.size()); } @Test(timeout = 60000) public void testBulkWriteNullArg() throws Exception { String name = String.format("dlserver-bulk-write-%s", "null"); dlClient.routingService.addHost(name, dlServer.getAddress()); List<ByteBuffer> writes = new ArrayList<ByteBuffer>(); writes.add(null); try { List<Future<DLSN>> futureResult = dlClient.dlClient.writeBulk(name, writes); fail("should not have succeeded"); } catch (NullPointerException npe) { ; // expected } } @Test(timeout = 60000) public void testBulkWriteEmptyBuffer() throws Exception { String name = String.format("dlserver-bulk-write-%s", "empty"); dlClient.routingService.addHost(name, dlServer.getAddress()); List<ByteBuffer> writes = new ArrayList<ByteBuffer>(); writes.add(ByteBuffer.wrap(("").getBytes())); writes.add(ByteBuffer.wrap(("").getBytes())); List<Future<DLSN>> futures = dlClient.dlClient.writeBulk(name, writes); assertEquals(2, futures.size()); for (Future<DLSN> future : futures) { // No throw == pass DLSN dlsn = Await.result(future, Duration.fromSeconds(10)); } } void failDueToWrongException(Exception ex) { logger.info("testBulkWritePartialFailure: ", ex); fail(String.format("failed with wrong exception %s", ex.getClass().getName())); } int validateAllFailedAsCancelled(List<Future<DLSN>> futures, int start, int finish) { int failed = 0; for (int i = start; i < finish; i++) { Future<DLSN> future = futures.get(i); try { DLSN dlsn = Await.result(future, Duration.fromSeconds(10)); fail("future should have failed!"); } catch (DLException cre) { ++failed; } catch (Exception ex) { failDueToWrongException(ex); } } return failed; } void validateFailedAsLogRecordTooLong(Future<DLSN> future) { try { DLSN dlsn = Await.result(future, Duration.fromSeconds(10)); fail("should have failed"); } catch (DLException dle) { assertEquals(StatusCode.TOO_LARGE_RECORD, dle.getCode()); } catch (Exception ex) { failDueToWrongException(ex); } } @Test(timeout = 60000) public void testBulkWritePartialFailure() throws Exception { String name = String.format("dlserver-bulk-write-%s", "partial-failure"); dlClient.routingService.addHost(name, dlServer.getAddress()); final int writeCount = 100; List<ByteBuffer> writes = new ArrayList<ByteBuffer>(writeCount*2 + 1); for (long i = 1; i <= writeCount; i++) { writes.add(ByteBuffer.wrap(("" + i).getBytes())); } // Too big, will cause partial failure. ByteBuffer buf = ByteBuffer.allocate(MAX_LOGRECORD_SIZE + 1); writes.add(buf); for (long i = 1; i <= writeCount; i++) { writes.add(ByteBuffer.wrap(("" + i).getBytes())); } // Count succeeded. List<Future<DLSN>> futures = dlClient.dlClient.writeBulk(name, writes); int succeeded = 0; for (int i = 0; i < writeCount; i++) { Future<DLSN> future = futures.get(i); try { DLSN dlsn = Await.result(future, Duration.fromSeconds(10)); ++succeeded; } catch (Exception ex) { failDueToWrongException(ex); } } validateFailedAsLogRecordTooLong(futures.get(writeCount)); FutureUtils.result(Futures.collect(futures.subList(writeCount + 1, 2 * writeCount + 1))); assertEquals(writeCount, succeeded); } @Test(timeout = 60000) public void testBulkWriteTotalFailureFirstWriteFailed() throws Exception { String name = String.format("dlserver-bulk-write-%s", "first-write-failed"); dlClient.routingService.addHost(name, dlServer.getAddress()); final int writeCount = 100; List<ByteBuffer> writes = new ArrayList<ByteBuffer>(writeCount + 1); ByteBuffer buf = ByteBuffer.allocate(MAX_LOGRECORD_SIZE + 1); writes.add(buf); for (long i = 1; i <= writeCount; i++) { writes.add(ByteBuffer.wrap(("" + i).getBytes())); } List<Future<DLSN>> futures = dlClient.dlClient.writeBulk(name, writes); validateFailedAsLogRecordTooLong(futures.get(0)); FutureUtils.result(Futures.collect(futures.subList(1, writeCount + 1))); } @Test(timeout = 60000) public void testBulkWriteTotalFailureLostLock() throws Exception { String name = String.format("dlserver-bulk-write-%s", "lost-lock"); dlClient.routingService.addHost(name, dlServer.getAddress()); final int writeCount = 8; List<ByteBuffer> writes = new ArrayList<ByteBuffer>(writeCount + 1); ByteBuffer buf = ByteBuffer.allocate(8); writes.add(buf); for (long i = 1; i <= writeCount; i++) { writes.add(ByteBuffer.wrap(("" + i).getBytes())); } // Warm it up with a write. Await.result(dlClient.dlClient.write(name, ByteBuffer.allocate(8))); // Failpoint a lost lock, make sure the failure gets promoted to an operation failure. DistributedLogServiceImpl svcImpl = (DistributedLogServiceImpl) dlServer.dlServer.getLeft(); try { FailpointUtils.setFailpoint( FailpointUtils.FailPointName.FP_WriteInternalLostLock, FailpointUtils.FailPointActions.FailPointAction_Default ); Future<BulkWriteResponse> futures = svcImpl.writeBulkWithContext(name, writes, new WriteContext()); assertEquals(StatusCode.LOCKING_EXCEPTION, Await.result(futures).header.code); } finally { FailpointUtils.removeFailpoint( FailpointUtils.FailPointName.FP_WriteInternalLostLock ); } } @Test(timeout = 60000) public void testHeartbeat() throws Exception { String name = "dlserver-heartbeat"; dlClient.routingService.addHost(name, dlServer.getAddress()); for (long i = 1; i <= 10; i++) { logger.debug("Send heartbeat {} to stream {}.", i, name); dlClient.dlClient.check(name).get(); } logger.debug("Write entry one to stream {}.", name); dlClient.dlClient.write(name, ByteBuffer.wrap("1".getBytes())).get(); Thread.sleep(1000); DistributedLogManager dlm = DLMTestUtil.createNewDLM(name, conf, getUri()); LogReader reader = dlm.getInputStream(DLSN.InitialDLSN); int numRead = 0; // eid=0 => control records // other 9 heartbeats will not trigger writing any control records. // eid=1 => user entry long startEntryId = 1; LogRecordWithDLSN r = reader.readNext(false); while (null != r) { int i = Integer.parseInt(new String(r.getPayload())); assertEquals(numRead + 1, i); assertEquals(r.getDlsn().compareTo(new DLSN(1, startEntryId, 0)), 0); ++numRead; ++startEntryId; r = reader.readNext(false); } assertEquals(1, numRead); } @Test(timeout = 60000) public void testFenceWrite() throws Exception { String name = "dlserver-fence-write"; dlClient.routingService.addHost(name, dlServer.getAddress()); for (long i = 1; i <= 10; i++) { logger.debug("Write entry {} to stream {}.", i, name); dlClient.dlClient.write(name, ByteBuffer.wrap(("" + i).getBytes())).get(); } Thread.sleep(1000); logger.info("Fencing stream {}.", name); DLMTestUtil.fenceStream(conf, getUri(), name); logger.info("Fenced stream {}.", name); for (long i = 11; i <= 20; i++) { logger.debug("Write entry {} to stream {}.", i, name); dlClient.dlClient.write(name, ByteBuffer.wrap(("" + i).getBytes())).get(); } DistributedLogManager dlm = DLMTestUtil.createNewDLM(name, conf, getUri()); LogReader reader = dlm.getInputStream(1); int numRead = 0; LogRecord r = reader.readNext(false); while (null != r) { int i = Integer.parseInt(new String(r.getPayload())); assertEquals(numRead + 1, i); ++numRead; r = reader.readNext(false); } assertEquals(20, numRead); reader.close(); dlm.close(); } @Test(timeout = 60000) public void testDeleteStream() throws Exception { String name = "dlserver-delete-stream"; dlClient.routingService.addHost(name, dlServer.getAddress()); long txid = 101; for (long i = 1; i <= 10; i++) { long curTxId = txid++; logger.debug("Write entry {} to stream {}.", curTxId, name); dlClient.dlClient.write(name, ByteBuffer.wrap(("" + curTxId).getBytes())).get(); } checkStream(1, 1, 1, name, dlServer.getAddress(), true, true); dlClient.dlClient.delete(name).get(); checkStream(0, 0, 0, name, dlServer.getAddress(), false, false); Thread.sleep(1000); DistributedLogManager dlm101 = DLMTestUtil.createNewDLM(name, conf, getUri()); AsyncLogReader reader101 = FutureUtils.result(dlm101.openAsyncLogReader(DLSN.InitialDLSN)); try { FutureUtils.result(reader101.readNext()); fail("Should fail with LogNotFoundException since the stream is deleted"); } catch (LogNotFoundException lnfe) { // expected } FutureUtils.result(reader101.asyncClose()); dlm101.close(); txid = 201; for (long i = 1; i <= 10; i++) { long curTxId = txid++; logger.debug("Write entry {} to stream {}.", curTxId, name); DLSN dlsn = dlClient.dlClient.write(name, ByteBuffer.wrap(("" + curTxId).getBytes())).get(); } Thread.sleep(1000); DistributedLogManager dlm201 = DLMTestUtil.createNewDLM(name, conf, getUri()); LogReader reader201 = dlm201.getInputStream(1); int numRead = 0; int curTxId = 201; LogRecord r = reader201.readNext(false); while (null != r) { int i = Integer.parseInt(new String(r.getPayload())); assertEquals(curTxId++, i); ++numRead; r = reader201.readNext(false); } assertEquals(10, numRead); reader201.close(); dlm201.close(); } @Test(timeout = 60000) public void testCreateStream() throws Exception { try { setupNoAdHocCluster(); final String name = "dlserver-create-stream"; noAdHocClient.routingService.addHost("dlserver-create-stream", noAdHocServer.getAddress()); assertFalse(noAdHocServer.dlServer.getKey().getStreamManager().isAcquired(name)); assertTrue(Await.ready(noAdHocClient.dlClient.create(name)).isReturn()); long txid = 101; for (long i = 1; i <= 10; i++) { long curTxId = txid++; logger.debug("Write entry {} to stream {}.", curTxId, name); noAdHocClient.dlClient.write(name, ByteBuffer.wrap(("" + curTxId).getBytes())).get(); } assertTrue(noAdHocServer.dlServer.getKey().getStreamManager().isAcquired(name)); } finally { tearDownNoAdHocCluster(); } } /** This tests that create has touch like behavior in that trying to create the stream twice, simply does nothing */ @Test(timeout = 60000) public void testCreateStreamTwice() throws Exception { try { setupNoAdHocCluster(); final String name = "dlserver-create-stream-twice"; noAdHocClient.routingService.addHost("dlserver-create-stream-twice", noAdHocServer.getAddress()); assertFalse(noAdHocServer.dlServer.getKey().getStreamManager().isAcquired(name)); assertTrue(Await.ready(noAdHocClient.dlClient.create(name)).isReturn()); long txid = 101; for (long i = 1; i <= 10; i++) { long curTxId = txid++; logger.debug("Write entry {} to stream {}.", curTxId, name); noAdHocClient.dlClient.write(name, ByteBuffer.wrap(("" + curTxId).getBytes())).get(); } assertTrue(noAdHocServer.dlServer.getKey().getStreamManager().isAcquired(name)); // create again assertTrue(Await.ready(noAdHocClient.dlClient.create(name)).isReturn()); assertTrue(noAdHocServer.dlServer.getKey().getStreamManager().isAcquired(name)); } finally { tearDownNoAdHocCluster(); } } @Test(timeout = 60000) public void testTruncateStream() throws Exception { String name = "dlserver-truncate-stream"; dlClient.routingService.addHost(name, dlServer.getAddress()); long txid = 1; Map<Long, DLSN> txid2DLSN = new HashMap<Long, DLSN>(); for (int s = 1; s <= 3; s++) { for (long i = 1; i <= 10; i++) { long curTxId = txid++; logger.debug("Write entry {} to stream {}.", curTxId, name); DLSN dlsn = dlClient.dlClient.write(name, ByteBuffer.wrap(("" + curTxId).getBytes())).get(); txid2DLSN.put(curTxId, dlsn); } if (s <= 2) { dlClient.dlClient.release(name).get(); } } DLSN dlsnToDelete = txid2DLSN.get(21L); dlClient.dlClient.truncate(name, dlsnToDelete).get(); DistributedLogManager readDLM = DLMTestUtil.createNewDLM(name, conf, getUri()); LogReader reader = readDLM.getInputStream(1); int numRead = 0; int curTxId = 11; LogRecord r = reader.readNext(false); while (null != r) { int i = Integer.parseInt(new String(r.getPayload())); assertEquals(curTxId++, i); ++numRead; r = reader.readNext(false); } assertEquals(20, numRead); reader.close(); readDLM.close(); } @Test(timeout = 60000) public void testRequestDenied() throws Exception { String name = "request-denied"; dlClient.routingService.addHost(name, dlServer.getAddress()); AccessControlEntry ace = new AccessControlEntry(); ace.setDenyWrite(true); ZooKeeperClient zkc = TestZooKeeperClientBuilder .newBuilder() .uri(getUri()) .connectionTimeoutMs(60000) .sessionTimeoutMs(60000) .build(); DistributedLogNamespace dlNamespace = dlServer.dlServer.getLeft().getDistributedLogNamespace(); BKDLConfig bkdlConfig = BKDLConfig.resolveDLConfig(zkc, getUri()); String zkPath = getUri().getPath() + "/" + bkdlConfig.getACLRootPath() + "/" + name; ZKAccessControl accessControl = new ZKAccessControl(ace, zkPath); accessControl.create(zkc); AccessControlManager acm = dlNamespace.createAccessControlManager(); while (acm.allowWrite(name)) { Thread.sleep(100); } try { Await.result(dlClient.dlClient.write(name, ByteBuffer.wrap("1".getBytes(UTF_8)))); fail("Should fail with request denied exception"); } catch (DLException dle) { assertEquals(StatusCode.REQUEST_DENIED, dle.getCode()); } } @Test(timeout = 60000) public void testNoneStreamNameRegex() throws Exception { String streamNamePrefix = "none-stream-name-regex-"; int numStreams = 5; Set<String> streams = new HashSet<String>(); for (int i = 0; i < numStreams; i++) { streams.add(streamNamePrefix + i); } testStreamNameRegex(streams, ".*", streams); } @Test(timeout = 60000) public void testStreamNameRegex() throws Exception { String streamNamePrefix = "stream-name-regex-"; int numStreams = 5; Set<String> streams = new HashSet<String>(); Set<String> expectedStreams = new HashSet<String>(); String streamNameRegex = streamNamePrefix + "1"; for (int i = 0; i < numStreams; i++) { streams.add(streamNamePrefix + i); } expectedStreams.add(streamNamePrefix + "1"); testStreamNameRegex(streams, streamNameRegex, expectedStreams); } private void testStreamNameRegex(Set<String> streams, String streamNameRegex, Set<String> expectedStreams) throws Exception { for (String streamName : streams) { dlClient.routingService.addHost(streamName, dlServer.getAddress()); Await.result(dlClient.dlClient.write(streamName, ByteBuffer.wrap(streamName.getBytes(UTF_8)))); } DLClient client = createDistributedLogClient("test-stream-name-regex", streamNameRegex); try { client.routingService.addHost("unknown", dlServer.getAddress()); client.handshake(); Map<SocketAddress, Set<String>> distribution = client.dlClient.getStreamOwnershipDistribution(); assertEquals(1, distribution.size()); Set<String> cachedStreams = distribution.values().iterator().next(); assertNotNull(cachedStreams); assertEquals(expectedStreams.size(), cachedStreams.size()); for (String streamName : cachedStreams) { assertTrue(expectedStreams.contains(streamName)); } } finally { client.shutdown(); } } @Test(timeout = 60000) public void testReleaseStream() throws Exception { String name = "dlserver-release-stream"; dlClient.routingService.addHost(name, dlServer.getAddress()); Await.result(dlClient.dlClient.write(name, ByteBuffer.wrap("1".getBytes(UTF_8)))); checkStream(1, 1, 1, name, dlServer.getAddress(), true, true); // release the stream Await.result(dlClient.dlClient.release(name)); checkStream(0, 0, 0, name, dlServer.getAddress(), false, false); } @Test(timeout = 60000) public void testAcceptNewStream() throws Exception { String name = "dlserver-accept-new-stream"; dlClient.routingService.addHost(name, dlServer.getAddress()); dlClient.routingService.setAllowRetrySameHost(false); Await.result(dlClient.dlClient.setAcceptNewStream(false)); try { Await.result(dlClient.dlClient.write(name, ByteBuffer.wrap("1".getBytes(UTF_8)))); fail("Should fail because the proxy couldn't accept new stream"); } catch (NoBrokersAvailableException nbae) { // expected } checkStream(0, 0, 0, name, dlServer.getAddress(), false, false); Await.result(dlServer.dlServer.getLeft().setAcceptNewStream(true)); Await.result(dlClient.dlClient.write(name, ByteBuffer.wrap("1".getBytes(UTF_8)))); checkStream(1, 1, 1, name, dlServer.getAddress(), true, true); } private void checkStream(int expectedNumProxiesInClient, int expectedClientCacheSize, int expectedServerCacheSize, String name, SocketAddress owner, boolean existedInServer, boolean existedInClient) { Map<SocketAddress, Set<String>> distribution = dlClient.dlClient.getStreamOwnershipDistribution(); assertEquals(expectedNumProxiesInClient, distribution.size()); if (expectedNumProxiesInClient > 0) { Map.Entry<SocketAddress, Set<String>> localEntry = distribution.entrySet().iterator().next(); assertEquals(owner, localEntry.getKey()); assertEquals(expectedClientCacheSize, localEntry.getValue().size()); assertEquals(existedInClient, localEntry.getValue().contains(name)); } StreamManagerImpl streamManager = (StreamManagerImpl) dlServer.dlServer.getKey().getStreamManager(); Set<String> cachedStreams = streamManager.getCachedStreams().keySet(); Set<String> acquiredStreams = streamManager.getCachedStreams().keySet(); assertEquals(expectedServerCacheSize, cachedStreams.size()); assertEquals(existedInServer, cachedStreams.contains(name)); assertEquals(expectedServerCacheSize, acquiredStreams.size()); assertEquals(existedInServer, acquiredStreams.contains(name)); } }