content: /*
   * Copyright 1999-2018 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.service.dump;
  
  import com.alibaba.nacos.common.utils.MD5Utils;
  import com.alibaba.nacos.config.server.model.CacheItem;
  import com.alibaba.nacos.config.server.model.ConfigInfoWrapper;
  import com.alibaba.nacos.config.server.service.ConfigCacheService;
  import com.alibaba.nacos.config.server.service.ConfigMigrateService;
  import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskService;
  import com.alibaba.nacos.config.server.service.dump.disk.ConfigDiskServiceFactory;
  import com.alibaba.nacos.config.server.service.dump.disk.ConfigRocksDbDiskService;
  import com.alibaba.nacos.config.server.service.dump.processor.DumpProcessor;
  import com.alibaba.nacos.config.server.service.dump.task.DumpTask;
  import com.alibaba.nacos.config.server.service.repository.ConfigInfoGrayPersistService;
  import com.alibaba.nacos.config.server.service.repository.ConfigInfoPersistService;
  import com.alibaba.nacos.config.server.utils.GroupKey2;
  import com.alibaba.nacos.persistence.datasource.DataSourceService;
  import com.alibaba.nacos.persistence.datasource.DynamicDataSource;
  import com.alibaba.nacos.plugin.datasource.constants.CommonConstant;
  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.Mockito;
  import org.mockito.junit.jupiter.MockitoExtension;
  
  import java.io.IOException;
  import java.lang.reflect.Field;
  
  import static org.junit.jupiter.api.Assertions.assertEquals;
  import static org.junit.jupiter.api.Assertions.assertNull;
  import static org.junit.jupiter.api.Assertions.assertTrue;
  import static org.mockito.ArgumentMatchers.eq;
  import static org.mockito.Mockito.when;
  
  @ExtendWith(MockitoExtension.class)
  class DumpProcessorTest {
      
      @Mock
      DynamicDataSource dynamicDataSource;
      
      @Mock
      DataSourceService dataSourceService;
      
      @Mock
      ConfigInfoPersistService configInfoPersistService;
      
      @Mock
      ConfigInfoGrayPersistService configInfoGrayPersistService;
      
      @Mock
      ConfigMigrateService configMigrateService;
      
      ExternalDumpService dumpService;
      
      DumpProcessor dumpProcessor;
      
      MockedStatic<DynamicDataSource> dynamicDataSourceMockedStatic;
      
      MockedStatic<EnvUtil> envUtilMockedStatic;
      
      @BeforeEach
      void init() throws Exception {
          dynamicDataSourceMockedStatic = Mockito.mockStatic(DynamicDataSource.class);
          envUtilMockedStatic = Mockito.mockStatic(EnvUtil.class);
          when(EnvUtil.getNacosHome()).thenReturn(System.getProperty("user.home"));
          when(EnvUtil.getProperty(eq(CommonConstant.NACOS_PLUGIN_DATASOURCE_LOG), eq(Boolean.class),
                  eq(false))).thenReturn(false);
          when(EnvUtil.getProperty(eq("memory_limit_file_path"),
                  eq("/sys/fs/cgroup/memory/memory.limit_in_bytes"))).thenReturn(
                  "/sys/fs/cgroup/memory/memory.limit_in_bytes");
          
          dynamicDataSourceMockedStatic.when(DynamicDataSource::getInstance).thenReturn(dynamicDataSource);
          
          when(dynamicDataSource.getDataSource()).thenReturn(dataSourceService);
          
          dumpService = new ExternalDumpService(configInfoPersistService, null, null,
                  configInfoGrayPersistService, null, configMigrateService);
          dumpProcessor = new DumpProcessor(configInfoPersistService, configInfoGrayPersistService);
          Field[] declaredFields = ConfigDiskServiceFactory.class.getDeclaredFields();
          for (Field filed : declaredFields) {
              if (filed.getName().equals("configDiskService")) {
                  filed.setAccessible(true);
                  filed.set(null, createDiskService());
              }
          }
          
      }
      
      protected ConfigDiskService createDiskService() {
          return new ConfigRocksDbDiskService();
      }
      
      @AfterEach
      void after() throws Exception {
          dynamicDataSourceMockedStatic.close();
          envUtilMockedStatic.close();
          ConfigDiskServiceFactory.getInstance().clearAll();
          ConfigDiskServiceFactory.getInstance().clearAllGray();
      
          Field[] declaredFields = ConfigDiskServiceFactory.class.getDeclaredFields();
          for (Field filed : declaredFields) {
              if (filed.getName().equals("configDiskService")) {
                  filed.setAccessible(true);
                  filed.set(null, null);
              }
          }
      }
      
      @Test
      void testDumpNormalAndRemove() throws IOException {
          String dataId = "testDataId";
          String group = "testGroup";
          String tenant = "testTenant";
          String content = "testContent你好" + System.currentTimeMillis();
          long time = System.currentTimeMillis();
          ConfigInfoWrapper configInfoWrapper = new ConfigInfoWrapper();
          configInfoWrapper.setDataId(dataId);
          configInfoWrapper.setGroup(group);
          configInfoWrapper.setTenant(tenant);
          configInfoWrapper.setContent(content);
          configInfoWrapper.setLastModified(time);
          
          Mockito.when(configInfoPersistService.findConfigInfo(eq(dataId), eq(group), eq(tenant)))
                  .thenReturn(configInfoWrapper);
          
          String handlerIp = "127.0.0.1";
          long lastModified = System.currentTimeMillis();
          DumpTask dumpTask = new DumpTask(GroupKey2.getKey(dataId, group, tenant), null, lastModified, handlerIp);
          boolean process = dumpProcessor.process(dumpTask);
          assertTrue(process);
          
          //Check cache
          CacheItem contentCache = ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant));
          assertEquals(MD5Utils.md5Hex(content, "UTF-8"), contentCache.getConfigCache().getMd5());
          assertEquals(time, contentCache.getConfigCache().getLastModifiedTs());
          //check disk
          String contentFromDisk = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant);
          assertEquals(content, contentFromDisk);
          
          // remove
          Mockito.when(configInfoPersistService.findConfigInfo(eq(dataId), eq(group), eq(tenant))).thenReturn(null);
          
          boolean processRemove = dumpProcessor.process(dumpTask);
          assertTrue(processRemove);
          
          //Check cache
          CacheItem contentCacheAfterRemove = ConfigCacheService.getContentCache(GroupKey2.getKey(dataId, group, tenant));
          assertTrue(contentCacheAfterRemove == null);
          //check disk
          String contentFromDiskAfterRemove = ConfigDiskServiceFactory.getInstance().getContent(dataId, group, tenant);
          assertNull(contentFromDiskAfterRemove);
          
      }
  }
  