diff --git a/common/src/test/java/com/alibaba/nacos/common/notify/DefaultSharePublisherTest.java b/common/src/test/java/com/alibaba/nacos/common/notify/DefaultSharePublisherTest.java index 3d297743186..834c8e632a3 100644 --- a/common/src/test/java/com/alibaba/nacos/common/notify/DefaultSharePublisherTest.java +++ b/common/src/test/java/com/alibaba/nacos/common/notify/DefaultSharePublisherTest.java @@ -106,7 +106,7 @@ void testIgnoreExpiredEvent() throws InterruptedException { defaultSharePublisher.addSubscriber(smartSubscriber2, MockSlowEvent2.class); defaultSharePublisher.publish(mockSlowEvent1); defaultSharePublisher.publish(mockSlowEvent2); - TimeUnit.MILLISECONDS.sleep(1100); + TimeUnit.MILLISECONDS.sleep(1500); verify(smartSubscriber1).onEvent(mockSlowEvent1); verify(smartSubscriber2).onEvent(mockSlowEvent2); reset(smartSubscriber1); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/configuration/NacosConfigConfiguration.java b/config/src/main/java/com/alibaba/nacos/config/server/configuration/NacosConfigConfiguration.java index 1c6038c2f72..f45a8679e39 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/configuration/NacosConfigConfiguration.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/configuration/NacosConfigConfiguration.java @@ -19,6 +19,7 @@ import com.alibaba.nacos.config.server.filter.CircuitFilter; import com.alibaba.nacos.config.server.filter.NacosWebFilter; import com.alibaba.nacos.persistence.configuration.condition.ConditionDistributedEmbedStorage; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; @@ -34,6 +35,7 @@ public class NacosConfigConfiguration { @Bean + @ConditionalOnProperty(name = "nacos.web.charset.filter", havingValue = "nacos", matchIfMissing = true) public FilterRegistrationBean nacosWebFilterRegistration() { FilterRegistrationBean registration = new FilterRegistrationBean<>(); registration.setFilter(nacosWebFilter()); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/CacheItem.java b/config/src/main/java/com/alibaba/nacos/config/server/model/CacheItem.java index e0423f3daa7..edb7d741a68 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/CacheItem.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/CacheItem.java @@ -35,7 +35,7 @@ public class CacheItem { public String type; - ConfigCache configCache = new ConfigCache(); + ConfigCache configCache = ConfigCacheFactoryDelegate.getInstance().createConfigCache(); /** * Use for gray. @@ -92,7 +92,7 @@ public void initConfigGrayIfEmpty() { public void initConfigGrayIfEmpty(String grayName) { initConfigGrayIfEmpty(); if (!this.configCacheGray.containsKey(grayName)) { - this.configCacheGray.put(grayName, new ConfigCacheGray(grayName)); + this.configCacheGray.put(grayName, ConfigCacheFactoryDelegate.getInstance().createConfigCacheGray(grayName)); } } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCache.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCache.java index 21e43ab23c7..c1aa1643ae6 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCache.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCache.java @@ -21,8 +21,6 @@ import java.io.Serializable; -import static java.nio.charset.StandardCharsets.UTF_8; - /** * config cache . * @@ -30,9 +28,7 @@ */ public class ConfigCache implements Serializable { - volatile String md5Gbk = Constants.NULL; - - volatile String md5Utf8 = Constants.NULL; + volatile String md5 = Constants.NULL; volatile String encryptedDataKey; @@ -42,8 +38,7 @@ public class ConfigCache implements Serializable { * clear cache. */ public void clear() { - this.md5Gbk = Constants.NULL; - this.md5Utf8 = Constants.NULL; + this.md5 = Constants.NULL; this.encryptedDataKey = null; this.lastModifiedTs = -1L; } @@ -51,12 +46,13 @@ public void clear() { public ConfigCache() { } - public String getMd5(String encode) { - if (UTF_8.name().equalsIgnoreCase(encode)) { - return md5Utf8; - } else { - return md5Gbk; - } + public ConfigCache(String md5, long lastModifiedTs) { + this.md5 = StringPool.get(md5); + this.lastModifiedTs = lastModifiedTs; + } + + public String getMd5() { + return md5; } public String getEncryptedDataKey() { @@ -67,26 +63,8 @@ public void setEncryptedDataKey(String encryptedDataKey) { this.encryptedDataKey = encryptedDataKey; } - public ConfigCache(String md5Gbk, String md5Utf8, long lastModifiedTs) { - this.md5Gbk = StringPool.get(md5Gbk); - this.md5Utf8 = StringPool.get(md5Utf8); - this.lastModifiedTs = lastModifiedTs; - } - - public String getMd5Gbk() { - return md5Gbk; - } - - public void setMd5Gbk(String md5Gbk) { - this.md5Gbk = StringPool.get(md5Gbk); - } - - public String getMd5Utf8() { - return md5Utf8; - } - - public void setMd5Utf8(String md5Utf8) { - this.md5Utf8 = StringPool.get(md5Utf8); + public void setMd5(String md5) { + this.md5 = StringPool.get(md5); } public long getLastModifiedTs() { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheFactory.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheFactory.java new file mode 100644 index 00000000000..bf9d86c8f66 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheFactory.java @@ -0,0 +1,46 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.model; + +/** + * The interface Config cache factory. + * + * @author Sunrisea + */ +public interface ConfigCacheFactory { + + /** + * Create config cache config cache. + * + * @return the config cache + */ + public ConfigCache createConfigCache(); + + /** + * Create config cache gray config cache gray. + * + * @return the config cache gray + */ + public ConfigCacheGray createConfigCacheGray(); + + /** + * Gets config cache factroy name. + * + * @return the config cache factory name + */ + public String getName(); +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheFactoryDelegate.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheFactoryDelegate.java new file mode 100644 index 00000000000..643bfe9c38b --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheFactoryDelegate.java @@ -0,0 +1,119 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.model; + +import com.alibaba.nacos.common.spi.NacosServiceLoader; +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; + +/** + * The type Config cache factory delegate. + * + * @author Sunrisea + */ +public class ConfigCacheFactoryDelegate { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCacheFactoryDelegate.class); + + private static final ConfigCacheFactoryDelegate INSTANCE = new ConfigCacheFactoryDelegate(); + + private String configCacheFactoryType = EnvUtil.getProperty("nacos.config.cache.type", "nacos"); + + private ConfigCacheFactory configCacheFactory = null; + + private ConfigCacheFactoryDelegate() { + Collection configCacheFactories = NacosServiceLoader.load(ConfigCacheFactory.class); + for (ConfigCacheFactory each : configCacheFactories) { + if (StringUtils.isEmpty(each.getName())) { + LOGGER.warn( + "[ConfigCacheFactoryDelegate] Load ConfigCacheFactory({}) ConfigFactroyName (null/empty) fail. " + + "Please add ConfigFactoryName to resolve", each.getClass().getName()); + continue; + } + LOGGER.info( + "[ConfigCacheFactoryDelegate] Load ConfigCacheFactory({}) ConfigCacheFactoryName({}) successfully. ", + each.getClass().getName(), each.getName()); + if (StringUtils.equals(configCacheFactoryType, each.getName())) { + LOGGER.info("[ConfigCacheFactoryDelegate] Matched ConfigCacheFactory found,set configCacheFactory={}", + each.getClass().getName()); + this.configCacheFactory = each; + } + } + if (this.configCacheFactory == null) { + LOGGER.info( + "[ConfigCacheFactoryDelegate] Matched ConfigCacheFactory not found, Load Default NacosConfigCacheFactory successfully."); + this.configCacheFactory = new NacosConfigCacheFactory(); + } + } + + /** + * Gets instance. + * + * @return the instance + */ + public static ConfigCacheFactoryDelegate getInstance() { + return INSTANCE; + } + + /** + * Create config cache config cache. + * + * @return the config cache + */ + public ConfigCache createConfigCache() { + return configCacheFactory.createConfigCache(); + } + + /** + * Create config cache config cache. + * + * @param md5 the md 5 + * @param lastModifiedTs the last modified ts + * @return the config cache + */ + public ConfigCache createConfigCache(String md5, long lastModifiedTs) { + ConfigCache configCache = this.createConfigCache(); + configCache.setMd5(md5); + configCache.setLastModifiedTs(lastModifiedTs); + return configCache; + } + + /** + * Create config cache gray config cache gray. + * + * @return the config cache gray + */ + public ConfigCacheGray createConfigCacheGray() { + return configCacheFactory.createConfigCacheGray(); + } + + /** + * Create config cache gray config cache gray. + * + * @param grayName the gray name + * @return the config cache gray + */ + public ConfigCacheGray createConfigCacheGray(String grayName) { + ConfigCacheGray configCacheGray = configCacheFactory.createConfigCacheGray(); + configCacheGray.setGrayName(grayName); + return configCacheGray; + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheGray.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheGray.java index f3c8ccfd700..be2a8d561bb 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheGray.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCacheGray.java @@ -41,6 +41,8 @@ public void clear() { super.clear(); } + public ConfigCacheGray() {} + public ConfigCacheGray(String grayName) { this.grayName = grayName; } @@ -49,15 +51,6 @@ public GrayRule getGrayRule() { return grayRule; } - public ConfigCacheGray(String md5Gbk, String md5Utf8, long lastModifiedTs, String grayRule) - throws RuntimeException { - super(md5Gbk, md5Utf8, lastModifiedTs); - this.grayRule = GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRule)); - if (this.grayRule == null || !this.grayRule.isValid()) { - throw new RuntimeException("raw gray rule is invalid"); - } - } - public String getGrayName() { return grayName; } diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessor.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessor.java new file mode 100644 index 00000000000..c21bdc54f99 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessor.java @@ -0,0 +1,40 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.model; + +/** + * The interface Config cache md5 post processor. + * + * @author Sunrisea + */ +public interface ConfigCachePostProcessor { + + /** + * Gets post processor name. + * + * @return the post processor name + */ + public String getName(); + + /** + * Post process. + * + * @param configCache the config cache + * @param content the content + */ + public void postProcess(ConfigCache configCache, String content); +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessorDelegate.java b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessorDelegate.java new file mode 100644 index 00000000000..981e5352eb6 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessorDelegate.java @@ -0,0 +1,76 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.model; + +import com.alibaba.nacos.common.spi.NacosServiceLoader; +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; + +/** + * The type Config cache md5 post processor delegate. + * + * @author Sunrisea + */ +public class ConfigCachePostProcessorDelegate { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConfigCacheFactoryDelegate.class); + + private static final ConfigCachePostProcessorDelegate INSTANCE = new ConfigCachePostProcessorDelegate(); + + private String configCacheMd5PostProcessorType = EnvUtil.getProperty("nacos.config.cache.type", "nacos"); + + private ConfigCachePostProcessor configCachePostProcessor; + + private ConfigCachePostProcessorDelegate() { + Collection processors = NacosServiceLoader.load(ConfigCachePostProcessor.class); + for (ConfigCachePostProcessor processor : processors) { + if (StringUtils.isEmpty(processor.getName())) { + LOGGER.warn( + "[ConfigCachePostProcessorDelegate] Load ConfigCachePostProcessor({}) PostProcessorName(null/empty) fail. " + + "Please add PostProcessorName to resolve", processor.getClass().getName()); + continue; + } + LOGGER.info( + "[ConfigCachePostProcessorDelegate] Load ConfigCachePostProcessor({}) PostProcessorName({}) successfully. ", + processor.getClass().getName(), processor.getName()); + if (StringUtils.equals(configCacheMd5PostProcessorType, processor.getName())) { + LOGGER.info( + "[ConfigCachePostProcessorDelegate] Matched ConfigCachePostProcessor found,set configCacheFactory={}", + processor.getClass().getName()); + this.configCachePostProcessor = processor; + } + } + if (configCachePostProcessor == null) { + LOGGER.info( + "[ConfigCachePostProcessorDelegate] Matched ConfigCachePostProcessor not found, " + + "load Default NacosConfigCachePostProcessor successfully"); + configCachePostProcessor = new NacosConfigCachePostProcessor(); + } + } + + public static ConfigCachePostProcessorDelegate getInstance() { + return INSTANCE; + } + + public void postProcess(ConfigCache configCache, String content) { + configCachePostProcessor.postProcess(configCache, content); + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/NacosConfigCacheFactory.java b/config/src/main/java/com/alibaba/nacos/config/server/model/NacosConfigCacheFactory.java new file mode 100644 index 00000000000..a8fd8168169 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/NacosConfigCacheFactory.java @@ -0,0 +1,40 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.model; + +/** + * The type Nacos config cache factory. + * + * @author Sunrisea + */ +public class NacosConfigCacheFactory implements ConfigCacheFactory { + + @Override + public ConfigCache createConfigCache() { + return new ConfigCache(); + } + + @Override + public ConfigCacheGray createConfigCacheGray() { + return new ConfigCacheGray(); + } + + @Override + public String getName() { + return "nacos"; + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/model/NacosConfigCachePostProcessor.java b/config/src/main/java/com/alibaba/nacos/config/server/model/NacosConfigCachePostProcessor.java new file mode 100644 index 00000000000..7a7b0f35e67 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/model/NacosConfigCachePostProcessor.java @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.model; + +/** + * The type Nacos config cache md 5 post processor. + * + * @author Sunrisea + */ +public class NacosConfigCachePostProcessor implements ConfigCachePostProcessor { + + @Override + public String getName() { + return "nacos"; + } + + @Override + public void postProcess(ConfigCache configCache, String content) { + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigCacheService.java b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigCacheService.java index da9ed9ef5f2..bb49cb84311 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigCacheService.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/ConfigCacheService.java @@ -22,6 +22,7 @@ import com.alibaba.nacos.config.server.model.CacheItem; import com.alibaba.nacos.config.server.model.ConfigCache; import com.alibaba.nacos.config.server.model.ConfigCacheGray; +import com.alibaba.nacos.config.server.model.ConfigCachePostProcessorDelegate; import com.alibaba.nacos.config.server.model.event.LocalDataChangeEvent; import com.alibaba.nacos.config.server.model.gray.GrayRule; import com.alibaba.nacos.config.server.model.gray.GrayRuleManager; @@ -124,7 +125,7 @@ public static boolean dumpWithMd5(String dataId, String group, String tenant, St DUMP_LOG.info( "[dump] md5 changed, update md5 and timestamp in jvm cache ,groupKey={}, newMd5={},oldMd5={},lastModifiedTs={}", groupKey, md5, localContentMd5, lastModifiedTs); - updateMd5(groupKey, md5, lastModifiedTs, encryptedDataKey); + updateMd5(groupKey, md5, content, lastModifiedTs, encryptedDataKey); } else if (newLastModified) { DUMP_LOG.info( "[dump] md5 consistent ,timestamp changed, update timestamp only in jvm cache ,groupKey={},lastModifiedTs={}", @@ -229,7 +230,7 @@ public static boolean dumpGray(String dataId, String group, String tenant, Strin "[dump-gray] md5 changed, update local jvm cache& local disk cache, groupKey={},grayName={}, " + "newMd5={},oldMd5={}, newGrayRule={}, oldGrayRule={},lastModifiedTs={}", groupKey, grayName, md5, localContentGrayMd5, grayRule, localGrayRule, lastModifiedTs); - updateGrayMd5(groupKey, grayName, grayRule, md5, lastModifiedTs, encryptedDataKey); + updateGrayMd5(groupKey, grayName, grayRule, md5, content, lastModifiedTs, encryptedDataKey); ConfigDiskServiceFactory.getInstance().saveGrayToDisk(dataId, group, tenant, grayName, content); } else if (grayRuleChanged) { @@ -349,16 +350,20 @@ public static boolean remove(String dataId, String group, String tenant) { /** * Update md5 value. * - * @param groupKey groupKey string value. - * @param md5Utf8 md5 string value. - * @param lastModifiedTs lastModifiedTs long value. + * @param groupKey the group key + * @param md5 the md 5 + * @param content the content + * @param lastModifiedTs the last modified ts + * @param encryptedDataKey the encrypted data key */ - public static void updateMd5(String groupKey, String md5Utf8, long lastModifiedTs, String encryptedDataKey) { + public static void updateMd5(String groupKey, String md5, String content, long lastModifiedTs, String encryptedDataKey) { CacheItem cache = makeSure(groupKey, encryptedDataKey); - if (cache.getConfigCache().getMd5Utf8() == null || !cache.getConfigCache().getMd5Utf8().equals(md5Utf8)) { - cache.getConfigCache().setMd5Utf8(md5Utf8); - cache.getConfigCache().setLastModifiedTs(lastModifiedTs); - cache.getConfigCache().setEncryptedDataKey(encryptedDataKey); + ConfigCache configCache = cache.getConfigCache(); + if (configCache.getMd5() == null || !configCache.getMd5().equals(md5)) { + configCache.setMd5(md5); + configCache.setLastModifiedTs(lastModifiedTs); + configCache.setEncryptedDataKey(encryptedDataKey); + ConfigCachePostProcessorDelegate.getInstance().postProcess(configCache, content); NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey)); } } @@ -366,23 +371,25 @@ public static void updateMd5(String groupKey, String md5Utf8, long lastModifiedT /** * Update gray md5 value. * - * @param groupKey groupKey string value. - * @param grayName grayName string value. - * @param grayRule grayRule string value. - * @param md5Utf8 md5UTF8 string value. - * @param lastModifiedTs lastModifiedTs long value. - * @param encryptedDataKey encryptedDataKey string value. + * @param groupKey the group key + * @param grayName the gray name + * @param grayRule the gray rule + * @param md5 the md 5 + * @param content the content + * @param lastModifiedTs the last modified ts + * @param encryptedDataKey the encrypted data key */ - private static void updateGrayMd5(String groupKey, String grayName, String grayRule, String md5Utf8, + public static void updateGrayMd5(String groupKey, String grayName, String grayRule, String md5, String content, long lastModifiedTs, String encryptedDataKey) { CacheItem cache = makeSure(groupKey, null); cache.initConfigGrayIfEmpty(grayName); ConfigCacheGray configCache = cache.getConfigCacheGray().get(grayName); - configCache.setMd5Utf8(md5Utf8); + configCache.setMd5(md5); configCache.setLastModifiedTs(lastModifiedTs); configCache.setEncryptedDataKey(encryptedDataKey); configCache.resetGrayRule(grayRule); cache.sortConfigGray(); + ConfigCachePostProcessorDelegate.getInstance().postProcess(configCache, content); NotifyCenter.publishEvent(new LocalDataChangeEvent(groupKey)); } @@ -394,11 +401,10 @@ public static String getContentMd5(String groupKey) { } public static String getContentMd5(String groupKey, String ip, String tag) { - return getContentMd5(groupKey, ip, tag, null, ENCODE_UTF8); + return getContentMd5(groupKey, ip, tag, null); } - public static String getContentMd5(String groupKey, String ip, String tag, Map connLabels, - String encode) { + public static String getContentMd5(String groupKey, String ip, String tag, Map connLabels) { CacheItem item = CACHE.get(groupKey); if (item == null) { return NULL; @@ -419,11 +425,11 @@ public static String getContentMd5(String groupKey, String ip, String tag, Map appLabels) { - String serverMd5 = ConfigCacheService.getContentMd5(groupKey, ip, tag, appLabels, ENCODE_UTF8); + String serverMd5 = ConfigCacheService.getContentMd5(groupKey, ip, tag, appLabels); return StringUtils.equals(md5, serverMd5); } @@ -593,7 +599,7 @@ private static void updateTimeStamp(String groupKey, long lastModifiedTs, String * try config read lock with spin of try get lock times. * * @param groupKey group key of config. - * @return + * @return 0 - No data and failed. Positive number - lock succeeded. Negative number - lock failed. */ public static int tryConfigReadLock(String groupKey) { diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/FormalHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/FormalHandler.java index 660c956f3ce..dccbe620ca0 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/FormalHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/FormalHandler.java @@ -23,8 +23,6 @@ import java.io.IOException; -import static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8; - /** * Formal Handler. * This class represents a formal handler in the configuration query processing chain. @@ -49,7 +47,7 @@ public ConfigQueryChainResponse handle(ConfigQueryChainRequest request) throws I String tenant = request.getTenant(); CacheItem cacheItem = ConfigChainEntryHandler.getThreadLocalCacheItem(); - String md5 = cacheItem.getConfigCache().getMd5(ENCODE_UTF8); + String md5 = cacheItem.getConfigCache().getMd5(); long lastModified = cacheItem.getConfigCache().getLastModifiedTs(); String encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey(); String contentType = cacheItem.getType(); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/GrayRuleMatchHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/GrayRuleMatchHandler.java index e95640539d9..412fd8d78ef 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/GrayRuleMatchHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/GrayRuleMatchHandler.java @@ -24,8 +24,6 @@ import java.io.IOException; -import static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8; - /** * GrayRuleMatchHandler. * This class represents a gray rule handler in the configuration query processing chain. @@ -60,7 +58,7 @@ public ConfigQueryChainResponse handle(ConfigQueryChainRequest request) throws I ConfigQueryChainResponse response = new ConfigQueryChainResponse(); long lastModified = matchedGray.getLastModifiedTs(); - String md5 = matchedGray.getMd5(ENCODE_UTF8); + String md5 = matchedGray.getMd5(); String encryptedDataKey = matchedGray.getEncryptedDataKey(); String content = ConfigDiskServiceFactory.getInstance() .getGrayContent(request.getDataId(), request.getGroup(), request.getTenant(), diff --git a/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/SpecialTagNotFoundHandler.java b/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/SpecialTagNotFoundHandler.java index 08dee4c44ce..900e755ecf9 100644 --- a/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/SpecialTagNotFoundHandler.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/service/query/handler/SpecialTagNotFoundHandler.java @@ -24,8 +24,6 @@ import java.io.IOException; -import static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8; - /** * SpecialTagNotFound Handler. * This class represents special tag not found handler in the configuration query processing chain. @@ -51,7 +49,7 @@ public ConfigQueryChainResponse handle(ConfigQueryChainRequest request) throws I String tenant = request.getTenant(); CacheItem cacheItem = ConfigChainEntryHandler.getThreadLocalCacheItem(); - String md5 = cacheItem.getConfigCache().getMd5(ENCODE_UTF8); + String md5 = cacheItem.getConfigCache().getMd5(); long lastModified = cacheItem.getConfigCache().getLastModifiedTs(); String encryptedDataKey = cacheItem.getConfigCache().getEncryptedDataKey(); String contentType = cacheItem.getType(); diff --git a/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5Util.java b/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5Util.java index 9d9faa84a91..16b170dabc6 100755 --- a/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5Util.java +++ b/config/src/main/java/com/alibaba/nacos/config/server/utils/MD5Util.java @@ -17,7 +17,6 @@ package com.alibaba.nacos.config.server.utils; import com.alibaba.nacos.config.server.constant.Constants; -import com.alibaba.nacos.config.server.service.ConfigCacheService; import com.alibaba.nacos.core.utils.StringPool; import com.alibaba.nacos.common.utils.StringUtils; @@ -35,7 +34,6 @@ import java.util.List; import java.util.Map; -import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG; import static com.alibaba.nacos.config.server.constant.Constants.LINE_SEPARATOR; import static com.alibaba.nacos.config.server.constant.Constants.WORD_SEPARATOR; @@ -52,18 +50,7 @@ public class MD5Util { */ public static List compareMd5(HttpServletRequest request, HttpServletResponse response, Map clientMd5Map) { - List changedGroupKeys = new ArrayList<>(); - String tag = request.getHeader(VIPSERVER_TAG); - for (Map.Entry entry : clientMd5Map.entrySet()) { - String groupKey = entry.getKey(); - String clientMd5 = entry.getValue(); - String ip = RequestUtil.getRemoteIp(request); - boolean isUptodate = ConfigCacheService.isUptodate(groupKey, clientMd5, ip, tag); - if (!isUptodate) { - changedGroupKeys.add(groupKey); - } - } - return changedGroupKeys; + return Md5ComparatorDelegate.getInstance().compareMd5(request, response, clientMd5Map); } /** diff --git a/config/src/main/java/com/alibaba/nacos/config/server/utils/Md5Comparator.java b/config/src/main/java/com/alibaba/nacos/config/server/utils/Md5Comparator.java new file mode 100644 index 00000000000..aa183df791e --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/utils/Md5Comparator.java @@ -0,0 +1,48 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.utils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; +import java.util.Map; + +/** + * The interface Md5 comparator. + * + * @author Sunrisea + */ +public interface Md5Comparator { + + /** + * Gets md 5 comparator name. + * + * @return the md 5 comparator name + */ + public String getName(); + + /** + * Compare md 5 list. + * + * @param request the request + * @param response the response + * @param clientMd5Map the client md 5 map + * @return the list + */ + public List compareMd5(HttpServletRequest request, HttpServletResponse response, + Map clientMd5Map); +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/utils/Md5ComparatorDelegate.java b/config/src/main/java/com/alibaba/nacos/config/server/utils/Md5ComparatorDelegate.java new file mode 100644 index 00000000000..df95aa5ea60 --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/utils/Md5ComparatorDelegate.java @@ -0,0 +1,78 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.utils; + +import com.alibaba.nacos.common.spi.NacosServiceLoader; +import com.alibaba.nacos.common.utils.StringUtils; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * The type Md5 comparator delegate. + * + * @author Sunrisea + */ +public class Md5ComparatorDelegate { + + private static final Logger LOGGER = LoggerFactory.getLogger(Md5ComparatorDelegate.class); + + private static final Md5ComparatorDelegate INSTANCE = new Md5ComparatorDelegate(); + + private String md5ComparatorType = EnvUtil.getProperty("nacos.config.cache.type", "nacos"); + + private Md5Comparator md5Comparator; + + private Md5ComparatorDelegate() { + Collection md5Comparators = NacosServiceLoader.load(Md5Comparator.class); + for (Md5Comparator each : md5Comparators) { + if (StringUtils.isEmpty(each.getName())) { + LOGGER.warn( + "[Md5ComparatorDelegate] Load Md5Comparator({}) Md5ComparatorName(null/empty) fail. Please add Md5ComparatorName to resolve", + each.getClass().getName()); + continue; + } + LOGGER.info("[Md5ComparatorDelegate] Load Md5Comparator({}) Md5ComparatorName({}) successfully.", + each.getClass().getName(), each.getName()); + if (StringUtils.equals(md5ComparatorType, each.getName())) { + LOGGER.info("[Md5ComparatorDelegate] Matched Md5Comparator found,set md5Comparator={}", + each.getClass().getName()); + md5Comparator = each; + } + } + if (md5Comparator == null) { + LOGGER.info( + "[Md5ComparatorDelegate] Matched Md5Comparator not found, load Default NacosMd5Comparator successfully"); + md5Comparator = new NacosMd5Comparator(); + } + } + + public static Md5ComparatorDelegate getInstance() { + return INSTANCE; + } + + public List compareMd5(HttpServletRequest request, HttpServletResponse response, + Map clientMd5Map) { + return md5Comparator.compareMd5(request, response, clientMd5Map); + } +} diff --git a/config/src/main/java/com/alibaba/nacos/config/server/utils/NacosMd5Comparator.java b/config/src/main/java/com/alibaba/nacos/config/server/utils/NacosMd5Comparator.java new file mode 100644 index 00000000000..572cf26fb7c --- /dev/null +++ b/config/src/main/java/com/alibaba/nacos/config/server/utils/NacosMd5Comparator.java @@ -0,0 +1,57 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.utils; + +import com.alibaba.nacos.config.server.service.ConfigCacheService; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG; + +/** + * The type Nacos md5 comparator. + * + * @author Sunrisea + */ +public class NacosMd5Comparator implements Md5Comparator { + + @Override + public String getName() { + return "nacos"; + } + + @Override + public List compareMd5(HttpServletRequest request, HttpServletResponse response, + Map clientMd5Map) { + List changedGroupKeys = new ArrayList<>(); + String tag = request.getHeader(VIPSERVER_TAG); + for (Map.Entry entry : clientMd5Map.entrySet()) { + String groupKey = entry.getKey(); + String clientMd5 = entry.getValue(); + String ip = RequestUtil.getRemoteIp(request); + boolean isUptodate = ConfigCacheService.isUptodate(groupKey, clientMd5, ip, tag); + if (!isUptodate) { + changedGroupKeys.add(groupKey); + } + } + return changedGroupKeys; + } +} diff --git a/config/src/test/java/com/alibaba/nacos/config/server/controller/ConfigServletInnerTest.java b/config/src/test/java/com/alibaba/nacos/config/server/controller/ConfigServletInnerTest.java index a08073fd79d..80460c67d4f 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/controller/ConfigServletInnerTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/controller/ConfigServletInnerTest.java @@ -62,7 +62,6 @@ import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG; import static com.alibaba.nacos.config.server.constant.Constants.CONTENT_MD5; -import static com.alibaba.nacos.config.server.constant.Constants.ENCODE_GBK; import static com.alibaba.nacos.config.server.constant.Constants.ENCODE_UTF8; import static com.alibaba.nacos.config.server.utils.RequestUtil.CLIENT_APPNAME_HEADER; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -184,8 +183,7 @@ void testDoGetConfigV1Beta() throws Exception { private void mockGray4Beta(CacheItem cacheItem, String content, String betaIps, String dataKey) { cacheItem.initConfigGrayIfEmpty(BetaGrayRule.TYPE_BETA); ConfigCacheGray configCacheGray = cacheItem.getConfigCacheGray().get(BetaGrayRule.TYPE_BETA); - configCacheGray.setMd5Utf8(MD5Utils.md5Hex(content, ENCODE_UTF8)); - configCacheGray.setMd5Gbk(MD5Utils.md5Hex(content, ENCODE_GBK)); + configCacheGray.setMd5(MD5Utils.md5Hex(content, ENCODE_UTF8)); configCacheGray.setEncryptedDataKey(dataKey); ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(BetaGrayRule.TYPE_BETA, BetaGrayRule.VERSION, betaIps, -1000); @@ -196,8 +194,7 @@ private void mockGray4Beta(CacheItem cacheItem, String content, String betaIps, private void mockGray4Tag(CacheItem cacheItem, String content, String tagValue, String dataKey, long ts) { cacheItem.initConfigGrayIfEmpty(TagGrayRule.TYPE_TAG + "_" + tagValue); ConfigCacheGray configCacheGray = cacheItem.getConfigCacheGray().get(TagGrayRule.TYPE_TAG + "_" + tagValue); - configCacheGray.setMd5Utf8(MD5Utils.md5Hex(content, ENCODE_UTF8)); - configCacheGray.setMd5Gbk(MD5Utils.md5Hex(content, ENCODE_GBK)); + configCacheGray.setMd5(MD5Utils.md5Hex(content, ENCODE_UTF8)); configCacheGray.setLastModifiedTs(ts); configCacheGray.setEncryptedDataKey(dataKey); ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG, @@ -295,7 +292,7 @@ void testDoGetConfigFormal() throws Exception { CacheItem cacheItem = new CacheItem("test"); String md5 = "md5wertyui"; final String content = "content345678"; - cacheItem.getConfigCache().setMd5Utf8(md5); + cacheItem.getConfigCache().setMd5(md5); long ts = System.currentTimeMillis(); cacheItem.getConfigCache().setLastModifiedTs(ts); cacheItem.getConfigCache().setEncryptedDataKey("key2345678"); @@ -330,7 +327,7 @@ void testDoGetConfigFormalV2() throws Exception { CacheItem cacheItem = new CacheItem("test"); String md5 = "md5wertyui"; final String content = "content345678"; - cacheItem.getConfigCache().setMd5Utf8(md5); + cacheItem.getConfigCache().setMd5(md5); long ts = System.currentTimeMillis(); cacheItem.getConfigCache().setLastModifiedTs(ts); cacheItem.getConfigCache().setEncryptedDataKey("key2345678"); diff --git a/config/src/test/java/com/alibaba/nacos/config/server/model/ConfigCacheFactoryDelegateTest.java b/config/src/test/java/com/alibaba/nacos/config/server/model/ConfigCacheFactoryDelegateTest.java new file mode 100644 index 00000000000..e377a25e669 --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/model/ConfigCacheFactoryDelegateTest.java @@ -0,0 +1,90 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.model; + +import com.alibaba.nacos.common.spi.NacosServiceLoader; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.lang.reflect.Constructor; +import java.util.Collections; + +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class ConfigCacheFactoryDelegateTest { + + MockedStatic envUtilMockedStatic; + + MockedStatic nacosServiceLoaderMockedStatic; + + @Mock + NacosConfigCacheFactory nacosConfigCacheFactory; + + @BeforeEach + void setUp() { + envUtilMockedStatic = mockStatic(EnvUtil.class); + nacosServiceLoaderMockedStatic = mockStatic(NacosServiceLoader.class); + } + + @AfterEach + void tearDown() { + envUtilMockedStatic.close(); + nacosServiceLoaderMockedStatic.close(); + } + + @Test + public void test() { + nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(ConfigCacheFactory.class)) + .thenReturn(Collections.singletonList(nacosConfigCacheFactory)); + envUtilMockedStatic.when(() -> EnvUtil.getProperty("nacos.config.cache.type", "nacos")).thenReturn("lalala"); + ConfigCache configCache = ConfigCacheFactoryDelegate.getInstance().createConfigCache(); + ConfigCache configCache1 = ConfigCacheFactoryDelegate.getInstance().createConfigCache("md5", 123456789L); + ConfigCacheGray configCacheGray = ConfigCacheFactoryDelegate.getInstance().createConfigCacheGray("grayName"); + ConfigCacheGray configCacheGray1 = ConfigCacheFactoryDelegate.getInstance().createConfigCacheGray(); + verify(nacosConfigCacheFactory, times(0)).createConfigCache(); + verify(nacosConfigCacheFactory, times(0)).createConfigCacheGray(); + } + + @Test + public void test2() throws Exception { + when(nacosConfigCacheFactory.getName()).thenReturn("nacos"); + when(nacosConfigCacheFactory.createConfigCache()).thenReturn(new ConfigCache()); + when(nacosConfigCacheFactory.createConfigCacheGray()).thenReturn(new ConfigCacheGray()); + nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(ConfigCacheFactory.class)) + .thenReturn(Collections.singletonList(nacosConfigCacheFactory)); + envUtilMockedStatic.when(() -> EnvUtil.getProperty("nacos.config.cache.type", "nacos")).thenReturn("nacos"); + Constructor constructor = ConfigCacheFactoryDelegate.class.getDeclaredConstructor(); + constructor.setAccessible(true); + ConfigCacheFactoryDelegate configCacheFactoryDelegate = (ConfigCacheFactoryDelegate) constructor.newInstance(); + configCacheFactoryDelegate.createConfigCache(); + configCacheFactoryDelegate.createConfigCache("md5", 123456789L); + configCacheFactoryDelegate.createConfigCacheGray("grayName"); + configCacheFactoryDelegate.createConfigCacheGray(); + verify(nacosConfigCacheFactory, times(2)).createConfigCache(); + verify(nacosConfigCacheFactory, times(2)).createConfigCacheGray(); + } +} \ No newline at end of file diff --git a/config/src/test/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessorDelegateTest.java b/config/src/test/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessorDelegateTest.java new file mode 100644 index 00000000000..a68d78d5b40 --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/model/ConfigCachePostProcessorDelegateTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.model; + +import com.alibaba.nacos.common.spi.NacosServiceLoader; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Modifier; +import java.util.Collections; + +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class ConfigCachePostProcessorDelegateTest { + + MockedConstruction mockedConstruction; + + MockedStatic envUtilMockedStatic; + + MockedStatic nacosServiceLoaderMockedStatic; + + @Mock + public NacosConfigCachePostProcessor mockConfigCacheMd5PostProcessor; + + @BeforeEach + void setUp() { + envUtilMockedStatic = mockStatic(EnvUtil.class); + nacosServiceLoaderMockedStatic = mockStatic(NacosServiceLoader.class); + } + + @AfterEach + void tearDown() { + envUtilMockedStatic.close(); + nacosServiceLoaderMockedStatic.close(); + } + + @Test + void test1() { + envUtilMockedStatic.when(() -> EnvUtil.getProperty("nacos.config.cache.type", "nacos")).thenReturn("lalala"); + nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(ConfigCachePostProcessor.class)) + .thenReturn(Collections.singletonList(mockConfigCacheMd5PostProcessor)); + ConfigCachePostProcessorDelegate.getInstance().postProcess(null, null); + verify(mockConfigCacheMd5PostProcessor, times(0)).postProcess(null, null); + } + + @Test + void test2() + throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { + when(mockConfigCacheMd5PostProcessor.getName()).thenReturn("nacos"); + doNothing().when(mockConfigCacheMd5PostProcessor).postProcess(null, null); + envUtilMockedStatic.when(() -> EnvUtil.getProperty("nacos.config.cache.type", "nacos")).thenReturn("nacos"); + nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(ConfigCachePostProcessor.class)) + .thenReturn(Collections.singletonList(mockConfigCacheMd5PostProcessor)); + Constructor constructor = ConfigCachePostProcessorDelegate.class.getDeclaredConstructor(); + constructor.setAccessible(true); + Field field = ConfigCachePostProcessorDelegate.class.getDeclaredField("INSTANCE"); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + field.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + ConfigCachePostProcessorDelegate delegate = (ConfigCachePostProcessorDelegate) constructor.newInstance(); + field.set(null, delegate); + ConfigCachePostProcessorDelegate.getInstance().postProcess(null, null); + verify(mockConfigCacheMd5PostProcessor, times(1)).postProcess(null, null); + } +} \ No newline at end of file diff --git a/config/src/test/java/com/alibaba/nacos/config/server/model/NacosConfigCacheFactoryTest.java b/config/src/test/java/com/alibaba/nacos/config/server/model/NacosConfigCacheFactoryTest.java new file mode 100644 index 00000000000..5c768056f13 --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/model/NacosConfigCacheFactoryTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.model; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class NacosConfigCacheFactoryTest { + + @Test + public void testCreateConfigCache() { + NacosConfigCacheFactory nacosConfigCacheFactory = new NacosConfigCacheFactory(); + ConfigCache configCache = nacosConfigCacheFactory.createConfigCache(); + assertEquals(ConfigCache.class, configCache.getClass()); + ConfigCacheGray configCacheGray = nacosConfigCacheFactory.createConfigCacheGray(); + assertEquals(ConfigCacheGray.class, configCacheGray.getClass()); + } + + @Test + public void testGetName() { + NacosConfigCacheFactory nacosConfigCacheFactory = new NacosConfigCacheFactory(); + assertEquals("nacos", nacosConfigCacheFactory.getName()); + } +} \ No newline at end of file diff --git a/config/src/test/java/com/alibaba/nacos/config/server/model/NacosConfigCachePostProcessorTest.java b/config/src/test/java/com/alibaba/nacos/config/server/model/NacosConfigCachePostProcessorTest.java new file mode 100644 index 00000000000..47c53c19439 --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/model/NacosConfigCachePostProcessorTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.model; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class NacosConfigCachePostProcessorTest { + + @Test + public void test() { + NacosConfigCachePostProcessor nacosConfigCacheMd5PostProcessor = new NacosConfigCachePostProcessor(); + assertEquals("nacos", nacosConfigCacheMd5PostProcessor.getName()); + nacosConfigCacheMd5PostProcessor.postProcess(null, null); + } +} \ No newline at end of file diff --git a/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandlerTest.java b/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandlerTest.java index 4715b525ea3..8a640a3e74c 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandlerTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/remote/ConfigQueryRequestHandlerTest.java @@ -107,8 +107,7 @@ void testGetNormal() throws Exception { when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService); CacheItem cacheItem = new CacheItem(groupKey); - cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK")); - cacheItem.getConfigCache().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8")); + cacheItem.getConfigCache().setMd5(MD5Utils.md5Hex(content, "UTF-8")); cacheItem.getConfigCache().setEncryptedDataKey("key_testGetNormal_NotDirectRead"); when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem); @@ -147,8 +146,7 @@ void testGetBeta() throws Exception { cacheItem.initConfigGrayIfEmpty(BetaGrayRule.TYPE_BETA); String content = "content_from_beta_notdirectreadÄãºÃ" + System.currentTimeMillis(); ConfigCacheGray configCacheGrayBeta = cacheItem.getConfigCacheGray().get(BetaGrayRule.TYPE_BETA); - configCacheGrayBeta.setMd5Gbk(MD5Utils.md5Hex(content, "GBK")); - configCacheGrayBeta.setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8")); + configCacheGrayBeta.setMd5(MD5Utils.md5Hex(content, "UTF-8")); configCacheGrayBeta.setEncryptedDataKey("key_testGetBeta_NotDirectRead"); ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(BetaGrayRule.TYPE_BETA, BetaGrayRule.VERSION, "127.0.0.1", -1000); @@ -188,8 +186,7 @@ void testGetTagNotFound() throws Exception { when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService); CacheItem cacheItem = new CacheItem(groupKey); - cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK")); - cacheItem.getConfigCache().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8")); + cacheItem.getConfigCache().setMd5(MD5Utils.md5Hex(content, "UTF-8")); cacheItem.getConfigCache().setEncryptedDataKey("key_testGetTag_NotFound"); when(ConfigCacheService.getContentCache(eq(groupKey))).thenReturn(cacheItem); @@ -232,8 +229,7 @@ void testGetTagWithTag() throws Exception { when(ConfigDiskServiceFactory.getInstance()).thenReturn(configRocksDbDiskService); CacheItem cacheItem = new CacheItem(groupKey); - cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK")); - cacheItem.getConfigCache().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8")); + cacheItem.getConfigCache().setMd5(MD5Utils.md5Hex(content, "UTF-8")); cacheItem.getConfigCache().setEncryptedDataKey("key_formal"); String specificTag = "specific_tag"; @@ -241,8 +237,7 @@ void testGetTagWithTag() throws Exception { ConfigCacheGray configCacheGrayTag = cacheItem.getConfigCacheGray() .get(TagGrayRule.TYPE_TAG + "_" + specificTag); String tagContent = "content_from_specific_tag_directreadÄãºÃ" + System.currentTimeMillis(); - configCacheGrayTag.setMd5Gbk(MD5Utils.md5Hex(tagContent, "GBK")); - configCacheGrayTag.setMd5Utf8(MD5Utils.md5Hex(tagContent, "UTF-8")); + configCacheGrayTag.setMd5(MD5Utils.md5Hex(tagContent, "UTF-8")); configCacheGrayTag.setEncryptedDataKey("key_testGetTag_NotDirectRead"); ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG, TagGrayRule.VERSION, specificTag, -999); @@ -291,12 +286,10 @@ void testGetTagAutoTag() throws Exception { String autoTag = "auto_tag"; CacheItem cacheItem = new CacheItem(groupKey); cacheItem.initConfigGrayIfEmpty(TagGrayRule.TYPE_TAG + "_" + autoTag); - cacheItem.getConfigCache().setMd5Gbk(MD5Utils.md5Hex(content, "GBK")); - cacheItem.getConfigCache().setMd5Utf8(MD5Utils.md5Hex(content, "UTF-8")); + cacheItem.getConfigCache().setMd5(MD5Utils.md5Hex(content, "UTF-8")); ConfigCacheGray configCacheGrayTag = cacheItem.getConfigCacheGray().get(TagGrayRule.TYPE_TAG + "_" + autoTag); String tagContent = "content_from_specific_tag_directreadÄãºÃ" + System.currentTimeMillis(); - configCacheGrayTag.setMd5Gbk(MD5Utils.md5Hex(tagContent, "GBK")); - configCacheGrayTag.setMd5Utf8(MD5Utils.md5Hex(tagContent, "UTF-8")); + configCacheGrayTag.setMd5(MD5Utils.md5Hex(tagContent, "UTF-8")); configCacheGrayTag.setEncryptedDataKey("key_testGetTag_AutoTag_NotDirectRead"); ConfigGrayPersistInfo configGrayPersistInfo = new ConfigGrayPersistInfo(TagGrayRule.TYPE_TAG, TagGrayRule.VERSION, autoTag, -999); diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/ClientTrackServiceTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/ClientTrackServiceTest.java index edb32244646..b8b79b60c15 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/ClientTrackServiceTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/ClientTrackServiceTest.java @@ -17,9 +17,13 @@ package com.alibaba.nacos.config.server.service; import com.alibaba.nacos.config.server.utils.GroupKey2; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.web.WebAppConfiguration; @@ -31,9 +35,19 @@ @WebAppConfiguration class ClientTrackServiceTest { + MockedStatic envUtilMockedStatic; + @BeforeEach void before() { ClientTrackService.clientRecords.clear(); + envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); + envUtilMockedStatic.when(() -> EnvUtil.getProperty("nacos.config.cache.type", "nacos")) + .thenReturn("nacos"); + } + + @AfterEach + void after() { + envUtilMockedStatic.close(); } @Test @@ -43,8 +57,9 @@ void testTrackClientMd5() { String group = "online"; String groupKey = GroupKey2.getKey(dataId, group); String md5 = "xxxxxxxxxxxxx"; + String content = "test"; - ConfigCacheService.updateMd5(groupKey, md5, System.currentTimeMillis(), ""); + ConfigCacheService.updateMd5(groupKey, md5, content, System.currentTimeMillis(), ""); ClientTrackService.trackClientMd5(clientIp, groupKey, md5); ClientTrackService.trackClientMd5(clientIp, groupKey, md5); @@ -54,7 +69,7 @@ void testTrackClientMd5() { assertEquals(1, ClientTrackService.subscriberCount()); //服务端数据更新 - ConfigCacheService.updateMd5(groupKey, md5 + "111", System.currentTimeMillis(), ""); + ConfigCacheService.updateMd5(groupKey, md5 + "111", content, System.currentTimeMillis(), ""); assertFalse(ClientTrackService.isClientUptodate(clientIp).get(groupKey)); } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigCacheServiceTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigCacheServiceTest.java index b23610b1e1b..cfa563e88c3 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigCacheServiceTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/ConfigCacheServiceTest.java @@ -98,7 +98,7 @@ void testDumpFormal() throws Exception { //verify cache. CacheItem contentCache1 = ConfigCacheService.getContentCache(groupKey); assertEquals(ts, contentCache1.getConfigCache().getLastModifiedTs()); - assertEquals(md5, contentCache1.getConfigCache().getMd5Utf8()); + assertEquals(md5, contentCache1.getConfigCache().getMd5()); assertEquals(type, contentCache1.getType()); assertEquals(encryptedDataKey, contentCache1.getConfigCache().getEncryptedDataKey()); Mockito.verify(configDiskService, times(1)).saveToDisk(eq(dataId), eq(group), eq(tenant), eq(content)); @@ -111,7 +111,7 @@ void testDumpFormal() throws Exception { Mockito.verify(configDiskService, times(1)).saveToDisk(eq(dataId), eq(group), eq(tenant), eq(contentNew)); assertEquals(newTs, contentCache1.getConfigCache().getLastModifiedTs()); String newMd5 = MD5Utils.md5Hex(contentNew, "UTF-8"); - assertEquals(newMd5, contentCache1.getConfigCache().getMd5Utf8()); + assertEquals(newMd5, contentCache1.getConfigCache().getMd5()); //modified ts old long oldTs2 = newTs - 123L; @@ -121,7 +121,7 @@ void testDumpFormal() throws Exception { Mockito.verify(configDiskService, times(0)).saveToDisk(eq(dataId), eq(group), eq(tenant), eq(contentWithOldTs)); //not change ts and md5 assertEquals(newTs, contentCache1.getConfigCache().getLastModifiedTs()); - assertEquals(newMd5, contentCache1.getConfigCache().getMd5Utf8()); + assertEquals(newMd5, contentCache1.getConfigCache().getMd5()); //modified ts new only long newTs2 = newTs + 123L; @@ -168,7 +168,7 @@ public void testDumpGray() throws Exception { encryptedDataKey); assertTrue(result); CacheItem contentCache = ConfigCacheService.getContentCache(groupKey); - assertEquals(md5, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(md5, contentCache.getConfigCacheGray().get(grayName).getMd5()); assertEquals(ts, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); Mockito.verify(configDiskService, times(1)) @@ -181,7 +181,7 @@ public void testDumpGray() throws Exception { boolean resultNew = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRule, contentNew, tsNew, encryptedDataKey); assertTrue(resultNew); - assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5()); assertEquals(tsNew, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); Mockito.verify(configDiskService, times(1)) @@ -193,7 +193,7 @@ public void testDumpGray() throws Exception { boolean resultOld = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRule, contentWithOldTs, tsOld, encryptedDataKey); assertTrue(resultOld); - assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5()); assertEquals(tsNew, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); Mockito.verify(configDiskService, times(0)) @@ -207,7 +207,7 @@ public void testDumpGray() throws Exception { boolean resultNew2 = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRuleNew, contentWithPrev, tsNew2, encryptedDataKey); assertTrue(resultNew2); - assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5()); assertEquals(tsNew2, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); assertEquals(GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRuleNew)), @@ -220,7 +220,7 @@ public void testDumpGray() throws Exception { boolean resultNew3 = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRulePrev, contentWithPrev2, tsNew3, encryptedDataKey); assertTrue(resultNew3); - assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5()); assertEquals(tsNew3, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); assertEquals(GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRuleNew)), @@ -232,7 +232,7 @@ public void testDumpGray() throws Exception { boolean resultNew4 = ConfigCacheService.dumpGray(dataId, group, tenant, grayName, grayRulePrev, contentWithPrev4, tsNew4, encryptedDataKey); assertTrue(resultNew4); - assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5Utf8()); + assertEquals(md5New, contentCache.getConfigCacheGray().get(grayName).getMd5()); assertEquals(tsNew3, contentCache.getConfigCacheGray().get(grayName).getLastModifiedTs()); assertEquals(encryptedDataKey, contentCache.getConfigCacheGray().get(grayName).getEncryptedDataKey()); assertEquals(GrayRuleManager.constructGrayRule(GrayRuleManager.deserializeConfigGrayPersistInfo(grayRuleNew)), diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/LongPollingServiceTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/LongPollingServiceTest.java index 79409b7cfa9..925d22162a1 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/LongPollingServiceTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/LongPollingServiceTest.java @@ -84,7 +84,6 @@ void before() { connectionControlManagerMockedStatic = Mockito.mockStatic(ControlManagerCenter.class); connectionControlManagerMockedStatic.when(() -> ControlManagerCenter.getInstance()).thenReturn(controlManagerCenter); Mockito.when(controlManagerCenter.getConnectionControlManager()).thenReturn(connectionControlManager); - } @AfterEach @@ -111,6 +110,9 @@ void testAddLongPollingClientHasNotEqualsMd5() throws IOException { clientMd5Map.put(groupKeyEquals, md5Equals0); String md5NotEquals1 = MD5Utils.md5Hex("countNotEquals", "UTF-8"); clientMd5Map.put(groupKeyNotEquals, md5NotEquals1); + MockedStatic md5UtilMockedStatic = Mockito.mockStatic(MD5Util.class); + md5UtilMockedStatic.when(() -> MD5Util.compareMd5(any(), any(), any())) + .thenReturn(Arrays.asList(groupKeyNotEquals)); HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class); Mockito.when(httpServletRequest.getHeader(eq(LongPollingService.LONG_POLLING_NO_HANG_UP_HEADER))).thenReturn(null); @@ -131,7 +133,7 @@ void testAddLongPollingClientHasNotEqualsMd5() throws IOException { //expect print not equals group Mockito.verify(printWriter, times(1)).println(eq(responseString)); Mockito.verify(httpServletResponse, times(1)).setStatus(eq(HttpServletResponse.SC_OK)); - + md5UtilMockedStatic.close(); } @Test diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorkerTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorkerTest.java index 614d655c90e..2ebb02fd5fd 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorkerTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpChangeConfigWorkerTest.java @@ -188,7 +188,7 @@ void testDumpChangeOfChangedConfigsNewTimestampOverride() { .getLastModifiedTs()); assertEquals(MD5Utils.md5Hex(configInfoWrapperNewForId1.getContent(), "UTF-8"), ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, "group" + 1, "tenant" + 1)).getConfigCache() - .getMd5Utf8()); + .getMd5()); } @Test @@ -224,7 +224,7 @@ void testDumpChangeOfChangedConfigsNewTimestampEqualMd5() { .getLastModifiedTs()); assertEquals(MD5Utils.md5Hex(configInfoWrapperNewForId1.getContent(), "UTF-8"), ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, "group" + 1, "tenant" + 1)).getConfigCache() - .getMd5Utf8()); + .getMd5()); } @@ -263,7 +263,7 @@ void testDumpChangeOfChangedConfigsOldTimestamp() { .getLastModifiedTs()); assertEquals(MD5Utils.md5Hex("content" + 1, "UTF-8"), ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, "group" + 1, "tenant" + 1)).getConfigCache() - .getMd5Utf8()); + .getMd5()); } @@ -302,7 +302,7 @@ void testDumpChangeOfChangedConfigsEqualsTimestampMd5Update() { .getLastModifiedTs()); assertEquals(MD5Utils.md5Hex(configInfoWrapperNewForId1.getContent(), "UTF-8"), ConfigCacheService.getContentCache(GroupKey.getKeyTenant(dataIdPrefix + 1, "group" + 1, "tenant" + 1)).getConfigCache() - .getMd5Utf8()); + .getMd5()); } diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorTest.java index 819063612a7..e3d8ccf93d8 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/DumpProcessorTest.java @@ -138,7 +138,7 @@ void testDumpNormalAndRemove() throws IOException { //Check cache CacheItem contentCache = ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant)); - assertEquals(MD5Utils.md5Hex(content, "UTF-8"), contentCache.getConfigCache().getMd5Utf8()); + assertEquals(MD5Utils.md5Hex(content, "UTF-8"), contentCache.getConfigCache().getMd5()); assertEquals(time, contentCache.getConfigCache().getLastModifiedTs()); //check disk String contentFromDisk = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant); diff --git a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessorTest.java b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessorTest.java index b765d3a2e72..4a5d90325df 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessorTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/service/dump/processor/DumpAllProcessorTest.java @@ -70,6 +70,8 @@ class DumpAllProcessorTest { MockedStatic dynamicDataSourceMockedStatic; + MockedStatic propertyUtilMockedStatic; + @Mock ConfigInfoPersistService configInfoPersistService; @@ -81,6 +83,8 @@ class DumpAllProcessorTest { void init() throws Exception { dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class); envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); + propertyUtilMockedStatic = Mockito.mockStatic(PropertyUtil.class); + propertyUtilMockedStatic.when(PropertyUtil::getAllDumpPageSize).thenReturn(100); dumpAllProcessor = new DumpAllProcessor(configInfoPersistService); when(EnvUtil.getNacosHome()).thenReturn(System.getProperty("user.home")); when(EnvUtil.getProperty(eq(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG), eq(Boolean.class), eq(false))).thenReturn(false); @@ -93,12 +97,14 @@ void init() throws Exception { dumpAllProcessor = new DumpAllProcessor(configInfoPersistService); envUtilMockedStatic.when(() -> EnvUtil.getProperty(eq("memory_limit_file_path"), eq("/sys/fs/cgroup/memory/memory.limit_in_bytes"))) .thenReturn(mockMem); + } @AfterEach void after() throws Exception { dynamicDataSourceMockedStatic.close(); envUtilMockedStatic.close(); + propertyUtilMockedStatic.close(); } private ConfigInfoWrapper createNewConfig(int id) { @@ -153,7 +159,7 @@ void testDumpAllOnStartUp() throws Exception { //Check cache CacheItem contentCache1 = ConfigCacheService.getContentCache( GroupKey2.getKey(configInfoWrapper1.getDataId(), configInfoWrapper1.getGroup(), configInfoWrapper1.getTenant())); - assertEquals(md51, contentCache1.getConfigCache().getMd5Utf8()); + assertEquals(md51, contentCache1.getConfigCache().getMd5()); // check if config1 is updated assertTrue(timestamp < contentCache1.getConfigCache().getLastModifiedTs()); //check disk @@ -164,7 +170,7 @@ void testDumpAllOnStartUp() throws Exception { //Check cache CacheItem contentCache2 = ConfigCacheService.getContentCache( GroupKey2.getKey(configInfoWrapper2.getDataId(), configInfoWrapper2.getGroup(), configInfoWrapper2.getTenant())); - assertEquals(MD5Utils.md5Hex(configInfoWrapper2.getContent(), "UTF-8"), contentCache2.getConfigCache().getMd5Utf8()); + assertEquals(MD5Utils.md5Hex(configInfoWrapper2.getContent(), "UTF-8"), contentCache2.getConfigCache().getMd5()); // check if config2 is updated assertEquals(timestamp, contentCache2.getConfigCache().getLastModifiedTs()); //check disk @@ -226,7 +232,7 @@ void testDumpAllOnCheckAll() throws Exception { CacheItem contentCache1 = ConfigCacheService.getContentCache( GroupKey2.getKey(configInfoWrapper1.getDataId(), configInfoWrapper1.getGroup(), configInfoWrapper1.getTenant())); // check if config1 is not updated - assertEquals(md51, contentCache1.getConfigCache().getMd5Utf8()); + assertEquals(md51, contentCache1.getConfigCache().getMd5()); assertEquals(latterTimestamp, contentCache1.getConfigCache().getLastModifiedTs()); //check disk String contentFromDisk1 = ConfigDiskServiceFactory.getInstance() @@ -237,7 +243,7 @@ void testDumpAllOnCheckAll() throws Exception { CacheItem contentCache2 = ConfigCacheService.getContentCache( GroupKey2.getKey(configInfoWrapper2.getDataId(), configInfoWrapper2.getGroup(), configInfoWrapper2.getTenant())); // check if config2 is updated - assertEquals(MD5Utils.md5Hex(configInfoWrapperSingle2.getContent(), "UTF-8"), contentCache2.getConfigCache().getMd5Utf8()); + assertEquals(MD5Utils.md5Hex(configInfoWrapperSingle2.getContent(), "UTF-8"), contentCache2.getConfigCache().getMd5()); assertEquals(configInfoWrapper2.getLastModified(), contentCache2.getConfigCache().getLastModifiedTs()); //check disk String contentFromDisk2 = ConfigDiskServiceFactory.getInstance() diff --git a/config/src/test/java/com/alibaba/nacos/config/server/utils/MD5UtilTest.java b/config/src/test/java/com/alibaba/nacos/config/server/utils/MD5UtilTest.java index 75ba6c1a82e..1ecdec56130 100644 --- a/config/src/test/java/com/alibaba/nacos/config/server/utils/MD5UtilTest.java +++ b/config/src/test/java/com/alibaba/nacos/config/server/utils/MD5UtilTest.java @@ -17,7 +17,10 @@ package com.alibaba.nacos.config.server.utils; import com.alibaba.nacos.config.server.service.ConfigCacheService; +import com.alibaba.nacos.sys.env.EnvUtil; import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; import org.mockito.Mockito; @@ -38,14 +41,36 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class MD5UtilTest { + MockedStatic envUtilMockedStatic; + + MockedStatic configCacheServiceMockedStatic; + + MockedStatic md5ComparatorDelegateMockedStatic; + + @BeforeEach + void setUp() { + envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class); + configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class); + md5ComparatorDelegateMockedStatic = Mockito.mockStatic(Md5ComparatorDelegate.class); + } + + @AfterEach + void tearDown() { + envUtilMockedStatic.close(); + configCacheServiceMockedStatic.close(); + md5ComparatorDelegateMockedStatic.close(); + } + @Test void testCompareMd5() { - - final MockedStatic configCacheServiceMockedStatic = Mockito.mockStatic(ConfigCacheService.class); + Md5ComparatorDelegate md5ComparatorDelegate = Mockito.mock(Md5ComparatorDelegate.class); + when(Md5ComparatorDelegate.getInstance()).thenReturn(md5ComparatorDelegate); when(ConfigCacheService.isUptodate(anyString(), anyString(), anyString(), anyString())).thenReturn(false); @@ -56,12 +81,12 @@ void testCompareMd5() { request.addHeader("Vipserver-Tag", "test"); MockHttpServletResponse response = new MockHttpServletResponse(); - List changedGroupKeys = MD5Util.compareMd5(request, response, clientMd5Map); + envUtilMockedStatic.when(() -> EnvUtil.getProperty("nacos.config.cache.type", "nacos")).thenReturn("nacos"); + when(md5ComparatorDelegate.compareMd5(request, response, clientMd5Map)).thenReturn(new ArrayList<>()); + MD5Util.compareMd5(request, response, clientMd5Map); - assertEquals(1, changedGroupKeys.size()); - assertEquals("test", changedGroupKeys.get(0)); + verify(md5ComparatorDelegate, times(1)).compareMd5(request, response, clientMd5Map); - configCacheServiceMockedStatic.close(); } @Test diff --git a/config/src/test/java/com/alibaba/nacos/config/server/utils/Md5ComparatorDelegateTest.java b/config/src/test/java/com/alibaba/nacos/config/server/utils/Md5ComparatorDelegateTest.java new file mode 100644 index 00000000000..640aad0f184 --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/utils/Md5ComparatorDelegateTest.java @@ -0,0 +1,105 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.utils; + +import com.alibaba.nacos.common.spi.NacosServiceLoader; +import com.alibaba.nacos.sys.env.EnvUtil; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedConstruction; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Collections; +import java.util.HashMap; + +import static org.mockito.Mockito.mockConstruction; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class Md5ComparatorDelegateTest { + + public MockedStatic envUtilMockedStatic; + + public MockedStatic nacosServiceLoaderMockedStatic; + + public MockedConstruction nacosMd5ComparatorMockedConstruction; + + @Mock + public NacosMd5Comparator nacosMd5Comparator; + + @BeforeEach + void setUp() { + envUtilMockedStatic = mockStatic(EnvUtil.class); + nacosServiceLoaderMockedStatic = mockStatic(NacosServiceLoader.class); + } + + @AfterEach + void tearDown() { + envUtilMockedStatic.close(); + nacosServiceLoaderMockedStatic.close(); + } + + @Test + public void test() { + envUtilMockedStatic.when(() -> EnvUtil.getProperty("nacos.config.cache.type", "nacos")).thenReturn("lalala"); + nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(Md5Comparator.class)) + .thenReturn(Collections.singletonList(nacosMd5Comparator)); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + HashMap clientMd5Map = new HashMap<>(); + nacosMd5ComparatorMockedConstruction = mockConstruction(NacosMd5Comparator.class, (mock, context) -> { + when(mock.compareMd5(request, response, clientMd5Map)).thenReturn(null); + }); + Md5ComparatorDelegate.getInstance().compareMd5(request, response, clientMd5Map); + verify(nacosMd5Comparator, times(0)).compareMd5(request, response, clientMd5Map); + nacosMd5ComparatorMockedConstruction.close(); + } + + @Test + public void test2() throws Exception { + when(nacosMd5Comparator.getName()).thenReturn("nacos"); + envUtilMockedStatic.when(() -> EnvUtil.getProperty("nacos.config.cache.type", "nacos")).thenReturn("nacos"); + nacosServiceLoaderMockedStatic.when(() -> NacosServiceLoader.load(Md5Comparator.class)) + .thenReturn(Collections.singletonList(nacosMd5Comparator)); + Constructor constructor = Md5ComparatorDelegate.class.getDeclaredConstructor(); + constructor.setAccessible(true); + Field field = Md5ComparatorDelegate.class.getDeclaredField("INSTANCE"); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + field.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + Md5ComparatorDelegate delegate = (Md5ComparatorDelegate) constructor.newInstance(); + field.set(null, delegate); + MockHttpServletRequest request = new MockHttpServletRequest(); + MockHttpServletResponse response = new MockHttpServletResponse(); + HashMap clientMd5Map = new HashMap<>(); + Md5ComparatorDelegate.getInstance().compareMd5(request, response, clientMd5Map); + verify(nacosMd5Comparator, times(1)).compareMd5(request, response, clientMd5Map); + } +} \ No newline at end of file diff --git a/config/src/test/java/com/alibaba/nacos/config/server/utils/NacosMd5ComparatorTest.java b/config/src/test/java/com/alibaba/nacos/config/server/utils/NacosMd5ComparatorTest.java new file mode 100644 index 00000000000..29c33f08092 --- /dev/null +++ b/config/src/test/java/com/alibaba/nacos/config/server/utils/NacosMd5ComparatorTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 1999-2024 Alibaba Group Holding 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 com.alibaba.nacos.config.server.utils; + +import com.alibaba.nacos.config.server.service.ConfigCacheService; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.junit.jupiter.MockitoExtension; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; +import java.util.List; + +import static com.alibaba.nacos.api.common.Constants.VIPSERVER_TAG; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class NacosMd5ComparatorTest { + + MockedStatic mockRequestUtil; + + MockedStatic configCacheServiceMockedStatic; + + @Mock + HttpServletRequest request; + + @Mock + HttpServletResponse response; + + @BeforeEach + void setUp() { + mockRequestUtil = mockStatic(RequestUtil.class); + configCacheServiceMockedStatic = mockStatic(ConfigCacheService.class); + } + + @AfterEach + void tearDown() { + mockRequestUtil.close(); + configCacheServiceMockedStatic.close(); + } + + @Test + void getName() { + NacosMd5Comparator nacosMd5Comparator = new NacosMd5Comparator(); + assertEquals("nacos", nacosMd5Comparator.getName()); + } + + @Test + void compareMd5NoChange() { + String ip = "127.0.0.1"; + String tag = "tag"; + when(request.getHeader(VIPSERVER_TAG)).thenReturn(tag); + mockRequestUtil.when(() -> RequestUtil.getRemoteIp(request)).thenReturn(ip); + + String groupKey1 = "groupKey1"; + String groupKey2 = "groupKey2"; + String clientMd5 = "clientMd5"; + HashMap clientMd5Map = new HashMap<>(); + clientMd5Map.put(groupKey1, clientMd5); + clientMd5Map.put(groupKey2, clientMd5); + + NacosMd5Comparator nacosMd5Comparator = new NacosMd5Comparator(); + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.isUptodate(anyString(), eq(clientMd5), eq(ip), eq(tag))).thenReturn(true); + + List changedGroupKeys = nacosMd5Comparator.compareMd5(request, response, clientMd5Map); + assertEquals(0, changedGroupKeys.size()); + } + + @Test + void compareMd5Change() { + String ip = "127.0.0.1"; + String tag = "tag"; + when(request.getHeader(VIPSERVER_TAG)).thenReturn(tag); + mockRequestUtil.when(() -> RequestUtil.getRemoteIp(request)).thenReturn(ip); + + String groupKey1 = "groupKey1"; + String groupKey2 = "groupKey2"; + String clientMd5 = "clientMd5"; + HashMap clientMd5Map = new HashMap<>(); + clientMd5Map.put(groupKey1, clientMd5); + clientMd5Map.put(groupKey2, clientMd5); + + NacosMd5Comparator nacosMd5Comparator = new NacosMd5Comparator(); + configCacheServiceMockedStatic.when( + () -> ConfigCacheService.isUptodate(anyString(), eq(clientMd5), eq(ip), eq(tag))).thenReturn(false); + + List changedGroupKeys = nacosMd5Comparator.compareMd5(request, response, clientMd5Map); + assertEquals(2, changedGroupKeys.size()); + } +} \ No newline at end of file