| /* |
| * 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.dubbo.metadata.store.redis; |
| |
| import org.apache.dubbo.common.URL; |
| import org.apache.dubbo.common.utils.JsonUtils; |
| import org.apache.dubbo.common.utils.NetUtils; |
| import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder; |
| import org.apache.dubbo.metadata.definition.model.FullServiceDefinition; |
| import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum; |
| import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier; |
| import org.apache.dubbo.rpc.RpcException; |
| |
| import org.apache.commons.lang3.SystemUtils; |
| import org.junit.jupiter.api.AfterEach; |
| import org.junit.jupiter.api.Assertions; |
| import org.junit.jupiter.api.BeforeEach; |
| import org.junit.jupiter.api.Test; |
| import org.junit.jupiter.api.TestInfo; |
| import redis.clients.jedis.Jedis; |
| import redis.clients.jedis.exceptions.JedisConnectionException; |
| import redis.clients.jedis.exceptions.JedisDataException; |
| import redis.embedded.RedisServer; |
| |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Random; |
| |
| import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE; |
| import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE; |
| import static org.apache.dubbo.common.constants.CommonConstants.SYNC_REPORT_KEY; |
| import static redis.embedded.RedisServer.newRedisServer; |
| |
| public class RedisMetadataReportTest { |
| |
| private static final String |
| REDIS_URL_TEMPLATE = "redis://%slocalhost:%d", |
| REDIS_PASSWORD = "チェリー", |
| REDIS_URL_AUTH_SECTION = "username:" + REDIS_PASSWORD + "@"; |
| |
| RedisMetadataReport redisMetadataReport; |
| RedisMetadataReport syncRedisMetadataReport; |
| RedisServer redisServer; |
| URL registryUrl; |
| |
| @BeforeEach |
| public void constructor(final TestInfo testInfo) throws IOException { |
| final boolean usesAuthentication = usesAuthentication(testInfo); |
| int redisPort = 0; |
| IOException exception = null; |
| |
| for (int i = 0; i < 10; i++) { |
| try { |
| redisPort = NetUtils.getAvailablePort(30000 + new Random().nextInt(10000)); |
| redisServer = newRedisServer() |
| .port(redisPort) |
| // set maxheap to fix Windows error 0x70 while starting redis |
| .settingIf(SystemUtils.IS_OS_WINDOWS, "maxheap 128mb") |
| .settingIf(usesAuthentication, "requirepass " + REDIS_PASSWORD) |
| .build(); |
| this.redisServer.start(); |
| exception = null; |
| } catch (IOException e) { |
| e.printStackTrace(); |
| exception = e; |
| } |
| if (exception == null) { |
| break; |
| } |
| } |
| |
| Assertions.assertNull(exception); |
| registryUrl = newRedisUrl(usesAuthentication, redisPort); |
| redisMetadataReport = (RedisMetadataReport) new RedisMetadataReportFactory().createMetadataReport(registryUrl); |
| URL syncRegistryUrl = registryUrl.addParameter(SYNC_REPORT_KEY, "true"); |
| syncRedisMetadataReport = (RedisMetadataReport) new RedisMetadataReportFactory().createMetadataReport(syncRegistryUrl); |
| } |
| |
| private static boolean usesAuthentication(final TestInfo testInfo) { |
| final String methodName = testInfo.getTestMethod().get().getName(); |
| return "testAuthRedisMetadata".equals(methodName) || "testWrongAuthRedisMetadata".equals(methodName); |
| } |
| |
| private static URL newRedisUrl(final boolean usesAuthentication, final int redisPort) { |
| final String urlAuthSection = usesAuthentication ? REDIS_URL_AUTH_SECTION : ""; |
| return URL.valueOf(String.format(REDIS_URL_TEMPLATE, urlAuthSection, redisPort)); |
| } |
| |
| @AfterEach |
| public void tearDown() throws Exception { |
| this.redisServer.stop(); |
| } |
| |
| @Test |
| public void testAsyncStoreProvider() throws ClassNotFoundException { |
| testStoreProvider(redisMetadataReport, "1.0.0.redis.md.p1", 3000); |
| } |
| |
| @Test |
| public void testSyncStoreProvider() throws ClassNotFoundException { |
| testStoreProvider(syncRedisMetadataReport, "1.0.0.redis.md.p2", 3); |
| } |
| |
| private void testStoreProvider(RedisMetadataReport redisMetadataReport, String version, long moreTime) throws ClassNotFoundException { |
| String interfaceName = "org.apache.dubbo.metadata.store.redis.RedisMetadata4TstService"; |
| String group = null; |
| String application = "vic.redis.md"; |
| MetadataIdentifier providerMetadataIdentifier = storePrivider(redisMetadataReport, interfaceName, version, group, application); |
| Jedis jedis = null; |
| try { |
| jedis = redisMetadataReport.pool.getResource(); |
| String keyTmp = providerMetadataIdentifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY); |
| String value = jedis.get(keyTmp); |
| if (value == null) { |
| Thread.sleep(moreTime); |
| value = jedis.get(keyTmp); |
| } |
| |
| Assertions.assertNotNull(value); |
| |
| FullServiceDefinition fullServiceDefinition = JsonUtils.getJson().toJavaObject(value, FullServiceDefinition.class); |
| Assertions.assertEquals(fullServiceDefinition.getParameters().get("paramTest"), "redisTest"); |
| } catch (Throwable e) { |
| throw new RpcException("Failed to put to redis . cause: " + e.getMessage(), e); |
| } finally { |
| if (jedis != null) { |
| jedis.del(providerMetadataIdentifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY)); |
| } |
| redisMetadataReport.pool.close(); |
| } |
| } |
| |
| @Test |
| public void testAsyncStoreConsumer() throws ClassNotFoundException { |
| testStoreConsumer(redisMetadataReport, "1.0.0.redis.md.c1", 3000); |
| } |
| |
| @Test |
| public void testSyncStoreConsumer() throws ClassNotFoundException { |
| testStoreConsumer(syncRedisMetadataReport, "1.0.0.redis.md.c2", 3); |
| } |
| |
| private void testStoreConsumer(RedisMetadataReport redisMetadataReport, String version, long moreTime) throws ClassNotFoundException { |
| String interfaceName = "org.apache.dubbo.metadata.store.redis.RedisMetadata4TstService"; |
| String group = null; |
| String application = "vic.redis.md"; |
| MetadataIdentifier consumerMetadataIdentifier = storeConsumer(redisMetadataReport, interfaceName, version, group, application); |
| Jedis jedis = null; |
| try { |
| jedis = redisMetadataReport.pool.getResource(); |
| String keyTmp = consumerMetadataIdentifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY); |
| String value = jedis.get(keyTmp); |
| if (value == null) { |
| Thread.sleep(moreTime); |
| value = jedis.get(keyTmp); |
| } |
| Assertions.assertEquals(value, "{\"paramConsumerTest\":\"redisCm\"}"); |
| } catch (Throwable e) { |
| throw new RpcException("Failed to put to redis . cause: " + e.getMessage(), e); |
| } finally { |
| if (jedis != null) { |
| jedis.del(consumerMetadataIdentifier.getUniqueKey(KeyTypeEnum.UNIQUE_KEY)); |
| } |
| redisMetadataReport.pool.close(); |
| } |
| } |
| |
| private MetadataIdentifier storePrivider(RedisMetadataReport redisMetadataReport, String interfaceName, String version, String group, String application) throws ClassNotFoundException { |
| URL url = URL.valueOf("xxx://" + NetUtils.getLocalAddress().getHostName() + ":4444/" + interfaceName + "?paramTest=redisTest&version=" + version + "&application=" |
| + application + (group == null ? "" : "&group=" + group)); |
| |
| MetadataIdentifier providerMetadataIdentifier = new MetadataIdentifier(interfaceName, version, group, PROVIDER_SIDE, application); |
| Class interfaceClass = Class.forName(interfaceName); |
| FullServiceDefinition fullServiceDefinition = ServiceDefinitionBuilder.buildFullDefinition(interfaceClass, url.getParameters()); |
| |
| redisMetadataReport.storeProviderMetadata(providerMetadataIdentifier, fullServiceDefinition); |
| try { |
| Thread.sleep(300); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| return providerMetadataIdentifier; |
| } |
| |
| private MetadataIdentifier storeConsumer(RedisMetadataReport redisMetadataReport, String interfaceName, String version, String group, String application) throws ClassNotFoundException { |
| URL url = URL.valueOf("xxx://" + NetUtils.getLocalAddress().getHostName() + ":4444/" + interfaceName + "?version=" + version + "&application=" |
| + application + (group == null ? "" : "&group=" + group)); |
| |
| MetadataIdentifier consumerMetadataIdentifier = new MetadataIdentifier(interfaceName, version, group, CONSUMER_SIDE, application); |
| Class interfaceClass = Class.forName(interfaceName); |
| |
| Map<String, String> tmp = new HashMap<>(); |
| tmp.put("paramConsumerTest", "redisCm"); |
| redisMetadataReport.storeConsumerMetadata(consumerMetadataIdentifier, tmp); |
| try { |
| Thread.sleep(300); |
| } catch (InterruptedException e) { |
| e.printStackTrace(); |
| } |
| return consumerMetadataIdentifier; |
| } |
| |
| @Test |
| public void testAuthRedisMetadata() throws ClassNotFoundException { |
| testStoreProvider(redisMetadataReport, "1.0.0.redis.md.p1", 3000); |
| } |
| |
| @Test |
| public void testWrongAuthRedisMetadata() throws ClassNotFoundException { |
| registryUrl = registryUrl.setPassword("123456"); |
| redisMetadataReport = (RedisMetadataReport) new RedisMetadataReportFactory().createMetadataReport(registryUrl); |
| try { |
| testStoreProvider(redisMetadataReport, "1.0.0.redis.md.p1", 3000); |
| } catch (RpcException e) { |
| if (e.getCause() instanceof JedisConnectionException && e.getCause().getCause() instanceof JedisDataException) { |
| Assertions.assertEquals("ERR invalid password", e.getCause().getCause().getMessage()); |
| } else { |
| Assertions.fail("no invalid password exception!"); |
| } |
| } |
| } |
| } |