/** * Copyright 2016 Netflix, Inc. * * 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 com.netflix.dyno.jedis; import com.netflix.dyno.connectionpool.*; import com.netflix.dyno.connectionpool.exception.DynoException; import com.netflix.dyno.connectionpool.impl.ConnectionContextImpl; import com.netflix.dyno.connectionpool.impl.OperationResultImpl; import com.netflix.dyno.connectionpool.impl.utils.ZipUtils; import org.junit.Assert; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import redis.clients.jedis.Jedis; import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static org.mockito.Matchers.*; import static org.mockito.Mockito.when; public class UnitTestConnectionPool implements ConnectionPool<Jedis> { Map<String, String> redis_data; @Mock Jedis client; @Mock Connection<Jedis> connection; private final ConnectionPoolConfiguration config; private final ConnectionContextImpl context = new ConnectionContextImpl(); private final OperationMonitor opMonitor; public UnitTestConnectionPool(ConnectionPoolConfiguration config, OperationMonitor opMonitor) { MockitoAnnotations.initMocks(this); this.config = config; this.opMonitor = opMonitor; this.redis_data = new HashMap<String, String>(); when(client.set(anyString(), anyString())).thenAnswer(new Answer<String>() { @Override public String answer(InvocationOnMock invocation) throws Throwable { String key = (String)invocation.getArguments()[0]; String value = (String)invocation.getArguments()[1]; redis_data.put(key, value); return value; } }); when(client.get(CompressionTest.VALUE_1KB)).thenReturn(CompressionTest.VALUE_1KB); when(client.get(CompressionTest.KEY_3KB)).thenAnswer(new Answer<String>() { @Override public String answer(InvocationOnMock invocation) throws Throwable { return ZipUtils.compressStringToBase64String(CompressionTest.VALUE_3KB); } }); when(client.get(CompressionTest.KEY_1KB)).thenReturn(CompressionTest.VALUE_1KB); when(client.hmset(anyString(), anyMap())).thenAnswer(new Answer<String>() { @Override public String answer(InvocationOnMock invocation) throws Throwable { Map<String, String> map = (Map<String, String>) invocation.getArguments()[1]; if (map != null) { if (map.containsKey(CompressionTest.KEY_3KB)) { if (ZipUtils.isCompressed(map.get(CompressionTest.KEY_3KB))) { return "OK"; } else { throw new RuntimeException("Value was not compressed"); } } } else { throw new RuntimeException("Map is NULL"); } return "OK"; } }); when(client.mget(Matchers.<String>anyVararg())).thenAnswer (new Answer<List<String>>() { @Override public List<String> answer(InvocationOnMock invocation) throws Throwable { // Get the keys passed Object[] keys = invocation.getArguments(); List<String> values = new ArrayList<String>(10); for (int i = 0; i < keys.length; i++) { // get the ith key, find the value in redis_data // if found, return that else return nil String key = (String)keys[i]; String value = redis_data.get(key); values.add(i, value); } return values; } }); } @Override public boolean addHost(Host host) { return true; } @Override public boolean removeHost(Host host) { return true; } @Override public boolean isHostUp(Host host) { return false; } @Override public boolean hasHost(Host host) { return false; } @Override public List<HostConnectionPool<Jedis>> getActivePools() { return null; } @Override public List<HostConnectionPool<Jedis>> getPools() { return null; } @Override public HostConnectionPool<Jedis> getHostPool(Host host) { return null; } @Override public <R> Collection<OperationResult<R>> executeWithRing(Operation<Jedis, R> op) throws DynoException { return null; } @Override public <R> ListenableFuture<OperationResult<R>> executeAsync(AsyncOperation<Jedis, R> op) throws DynoException { return null; } @Override public <R> OperationResult<R> executeWithFailover(Operation<Jedis, R> op) throws DynoException { try { R r = op.execute(client, context); if (context.hasMetadata("compression") || context.hasMetadata("decompression")) { opMonitor.recordSuccess(op.getName(), true); } else { opMonitor.recordSuccess(op.getName()); } return new OperationResultImpl<R>("Test", r, null); } finally { context.reset(); } } @Override public void shutdown() { } @Override public Future<Boolean> start() throws DynoException { return new Future<Boolean>() { @Override public boolean cancel(boolean mayInterruptIfRunning) { return false; } @Override public boolean isCancelled() { return false; } @Override public boolean isDone() { return false; } @Override public Boolean get() throws InterruptedException, ExecutionException { return true; } @Override public Boolean get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { return true; } }; } @Override public void idle() { } @Override public ConnectionPoolConfiguration getConfiguration() { return config; } @Override public HealthTracker<Jedis> getHealthTracker() { return null; } @Override public boolean isIdle() { return false; } @Override public Future<Boolean> updateHosts(Collection activeHosts, Collection inactiveHosts) { return null; } }