blob: c42c3f3360ee7180c959adbe9f850c6ca18bf825 [file] [log] [blame]
/*
* 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 org.apache.servicecomb.foundation.vertx.client;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import io.vertx.core.Context;
import io.vertx.core.Vertx;
import io.vertx.core.impl.VertxImpl;
import mockit.Deencapsulation;
import mockit.Expectations;
import mockit.Mock;
import mockit.MockUp;
import mockit.Mocked;
public class TestClientPoolManager {
@Mocked
Vertx vertx;
@Mocked
ClientPoolFactory<HttpClientWithContext> factory;
ClientPoolManager<HttpClientWithContext> poolMgr;
String id;
List<HttpClientWithContext> pools;
Map<Object, Object> contextMap = new HashMap<>();
@Mocked
Context context;
@Before
public void setup() {
poolMgr = new ClientPoolManager<>(vertx, factory);
id = Deencapsulation.getField(poolMgr, "id");
pools = Deencapsulation.getField(poolMgr, "pools");
new MockUp<Context>(context) {
@Mock
void put(Object key, Object value) {
contextMap.put(key, value);
}
@SuppressWarnings("unchecked")
@Mock
<T> T get(Object key) {
return (T) contextMap.get(key);
}
@Mock
Vertx owner() {
return vertx;
}
@Mock
boolean isEventLoopContext() {
return true;
}
};
}
@Test
public void createClientPool(@Mocked HttpClientWithContext pool) {
new Expectations(VertxImpl.class) {
{
factory.createClientPool(context);
result = pool;
}
};
Assertions.assertSame(pool, poolMgr.createClientPool(context));
Assertions.assertSame(pool, context.get(id));
MatcherAssert.assertThat(pools, Matchers.contains(pool));
}
@Test
public void findClientPool_sync(@Mocked HttpClientWithContext pool1, @Mocked HttpClientWithContext pool2) {
new Expectations(poolMgr) {
{
poolMgr.findThreadBindClientPool();
result = pool1;
poolMgr.findByContext(null);
result = pool2;
}
};
Assertions.assertSame(pool1, poolMgr.findClientPool(true));
Assertions.assertSame(pool2, poolMgr.findClientPool(false));
}
@Test
public void findThreadBindClientPool(@Mocked HttpClientWithContext pool1, @Mocked HttpClientWithContext pool2) {
pools.add(pool1);
pools.add(pool2);
new MockUp<Thread>() {
@Mock
long getId() {
return 0;
}
};
Assertions.assertSame(pool1, poolMgr.findThreadBindClientPool());
// find again, get the same result
Assertions.assertSame(pool1, poolMgr.findThreadBindClientPool());
new MockUp<Thread>() {
@Mock
long getId() {
return 1;
}
};
Assertions.assertSame(pool2, poolMgr.findThreadBindClientPool());
// find again, get the same result
Assertions.assertSame(pool2, poolMgr.findThreadBindClientPool());
}
@Test
public void findByContext_reactive() {
HttpClientWithContext notMatchPool1 = new HttpClientWithContext(null, null);
HttpClientWithContext notMatchPool2 = new HttpClientWithContext(null, null);
pools.add(notMatchPool1);
pools.add(notMatchPool2);
new Expectations() {
{
Vertx.currentContext();
result = context;
}
};
context.put(id, notMatchPool2);
Assertions.assertSame(notMatchPool2, poolMgr.findByContext());
// find again, get the same result
Assertions.assertSame(notMatchPool2, poolMgr.findByContext());
}
@Test
public void findByContext_wrongContext_reverse() {
HttpClientWithContext pool1 = new HttpClientWithContext(null, null);
HttpClientWithContext pool2 = new HttpClientWithContext(null, null);
pools.add(pool1);
pools.add(pool2);
new Expectations() {
{
Vertx.currentContext();
result = null;
}
};
AtomicInteger reactiveNextIndex = Deencapsulation.getField(poolMgr, "reactiveNextIndex");
reactiveNextIndex.set(Integer.MAX_VALUE);
// each time invoke find, reactiveNextIndex will inc 1
Assertions.assertSame(pool2, poolMgr.findByContext());
Assertions.assertSame(pool1, poolMgr.findByContext());
Assertions.assertSame(pool2, poolMgr.findByContext());
Assertions.assertSame(pool1, poolMgr.findByContext());
}
@Test
public void findByContext_normalThread() {
HttpClientWithContext pool = new HttpClientWithContext(null, null);
pools.add(pool);
new Expectations() {
{
Vertx.currentContext();
result = null;
}
};
Assertions.assertSame(pool, poolMgr.findByContext());
}
@Test
public void findByContext_otherVertx(@Mocked VertxImpl otherVertx, @Mocked Context otherContext) {
HttpClientWithContext pool = new HttpClientWithContext(null, null);
pools.add(pool);
new Expectations() {
{
Vertx.currentContext();
result = otherContext;
otherContext.owner();
result = otherVertx;
}
};
Assertions.assertSame(pool, poolMgr.findByContext());
}
@Test
public void findByContext_worker(@Mocked Context workerContext) {
HttpClientWithContext pool = new HttpClientWithContext(null, null);
pools.add(pool);
new Expectations() {
{
Vertx.currentContext();
result = workerContext;
workerContext.owner();
result = vertx;
workerContext.isEventLoopContext();
result = false;
}
};
Assertions.assertSame(pool, poolMgr.findByContext());
}
}