text: /*
   * Copyright 2017 Crown Copyright
   *
   * 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 stroom.data.store.impl.fs;
  
  import org.junit.jupiter.api.AfterAll;
  import org.junit.jupiter.api.AfterEach;
  import org.junit.jupiter.api.BeforeEach;
  import org.junit.jupiter.api.Test;
  import stroom.data.retention.impl.DataRetentionPolicyExecutor;
  import stroom.data.retention.impl.DataRetentionRulesService;
  import stroom.data.retention.shared.DataRetentionRule;
  import stroom.data.retention.shared.DataRetentionRules;
  import stroom.data.retention.shared.TimeUnit;
  import stroom.data.shared.StreamTypeNames;
  import stroom.data.store.api.Store;
  import stroom.data.store.api.Target;
  import stroom.data.store.api.TargetUtil;
  import stroom.data.store.impl.fs.DataVolumeDao.DataVolume;
  import stroom.docref.DocRef;
  import stroom.index.impl.selection.VolumeConfig;
  import stroom.meta.api.MetaProperties;
  import stroom.meta.shared.Meta;
  import stroom.meta.shared.MetaFields;
  import stroom.node.api.NodeInfo;
  import stroom.query.api.v2.ExpressionOperator;
  import stroom.query.api.v2.ExpressionOperator.Op;
  import stroom.query.api.v2.ExpressionTerm.Condition;
  import stroom.test.AbstractCoreIntegrationTest;
  import stroom.test.common.util.test.FileSystemTestUtil;
  import stroom.util.time.StroomDuration;
  
  import javax.inject.Inject;
  import java.io.IOException;
  import java.time.ZoneOffset;
  import java.time.ZonedDateTime;
  import java.util.Collections;
  import java.util.List;
  
  import static org.assertj.core.api.Assertions.assertThat;
  
  /**
   * Test the archiving stuff.
   * <p>
   * Create some old files and make sure they get archived.
   */
  class TestDataRetentionPolicyExecutor extends AbstractCoreIntegrationTest {
      private static final int REPLICATION_COUNT = 1;
      private static final int SIXTY = 60;
      private static final int FIFTY_FIVE = 55;
      private static final int FIFTY = 50;
  
      @Inject
      private VolumeConfig volumeConfig;
      @Inject
      private Store streamStore;
      @Inject
      private DataVolumeService dataVolumeService;
      //    @Inject
  //    private FeedStore feedStore;
      @Inject
      private FsCleanExecutor fileSystemCleanTaskExecutor;
      @Inject
      private NodeInfo nodeInfo;
      @Inject
      private DataRetentionRulesService dataRetentionRulesService;
      @Inject
      private DataRetentionPolicyExecutor dataRetentionPolicyExecutor;
      @Inject
      private PhysicalDeleteExecutor physicalDeleteExecutor;
      @Inject
      private DataStoreServiceConfig dataStoreServiceConfig;
  
      private int initialReplicationCount = 1;
  
      @BeforeEach
      void beforeEach() {
          initialReplicationCount = volumeConfig.getResilientReplicationCount();
          volumeConfig.setResilientReplicationCount(REPLICATION_COUNT);
      }
  
      @AfterEach
      void afterEach() {
          volumeConfig.setResilientReplicationCount(initialReplicationCount);
      }
  
      @Test
      void testCheckArchive() throws IOException {
          dataStoreServiceConfig.setFileSystemCleanOldAge(StroomDuration.ZERO);
          dataStoreServiceConfig.setDeletePurgeAge(StroomDuration.ZERO);
          fileSystemCleanTaskExecutor.clean();
  
          final ZonedDateTime oldDate = ZonedDateTime.now(ZoneOffset.UTC).minusDays(SIXTY);
          final ZonedDateTime newDate = ZonedDateTime.now(ZoneOffset.UTC).minusDays(FIFTY);
  
          // Write a file 2 files ... on we leave locked and the other not locked
          final String feedName = FileSystemTestUtil.getUniqueTestString();
  //        final DocRef feedRef = feedStore.createDocument(feedName);
  
          setupDataRetentionRules(feedName);
  
          final MetaProperties oldFile = new MetaProperties.Builder()
                  .feedName(feedName)
                  .typeName(StreamTypeNames.RAW_EVENTS)
                  .createMs(oldDate.toInstant().toEpochMilli())
                  .build();
          final MetaProperties newFile = new MetaProperties.Builder()
                  .feedName(feedName)
                  .typeName(StreamTypeNames.RAW_EVENTS)
                  .createMs(newDate.toInstant().toEpochMilli())
                  .build();
  
          Meta oldFileMeta;
          try (final Target oldFileTarget = streamStore.openTarget(oldFile)) {
              oldFileMeta = oldFileTarget.getMeta();
              TargetUtil.write(oldFileTarget, "MyTest");
          }
  
          Meta newFileMeta;
          try (final Target newFileTarget = streamStore.openTarget(newFile)) {
              newFileMeta = newFileTarget.getMeta();
              TargetUtil.write(newFileTarget, "MyTest");
          }
  
          List<DataVolume> oldVolumeList = dataVolumeService
                  .find(FindDataVolumeCriteria.create(oldFileMeta)).getValues();
          assertThat(oldVolumeList.size()).as("Expecting 1 stream volumes").isEqualTo(REPLICATION_COUNT);
  
          List<DataVolume> newVolumeList = dataVolumeService
                  .find(FindDataVolumeCriteria.create(newFileMeta)).getValues();
          assertThat(newVolumeList.size()).as("Expecting 1 stream volumes").isEqualTo(REPLICATION_COUNT);
  
          dataRetentionPolicyExecutor.exec();
          physicalDeleteExecutor.exec();
  
          // Test Again
          oldVolumeList = dataVolumeService.find(FindDataVolumeCriteria.create(oldFileMeta)).getValues();
          assertThat(oldVolumeList.size()).as("Expecting 0 stream volumes").isEqualTo(0);
  
          newVolumeList = dataVolumeService.find(FindDataVolumeCriteria.create(newFileMeta)).getValues();
          assertThat(newVolumeList.size()).as("Expecting 1 stream volumes").isEqualTo(REPLICATION_COUNT);
  
          // Test they are
          oldVolumeList = dataVolumeService.find(FindDataVolumeCriteria.create(oldFileMeta)).getValues();
          assertThat(oldVolumeList.size()).as("Expecting 0 stream volumes").isEqualTo(0);
          newVolumeList = dataVolumeService.find(FindDataVolumeCriteria.create(newFileMeta)).getValues();
          assertThat(newVolumeList.size()).as("Expecting 1 stream volumes").isEqualTo(REPLICATION_COUNT);
      }
  
      private void setupDataRetentionRules(final String feedName) {
          final DocRef docRef = dataRetentionRulesService.createDocument("test");
          DataRetentionRules dataRetentionRules = dataRetentionRulesService.readDocument(docRef);
  
          final ExpressionOperator.Builder builder = new ExpressionOperator.Builder(true, Op.AND);
          builder.addTerm(MetaFields.FEED_NAME, Condition.EQUALS, feedName);
          final DataRetentionRule rule = createRule(1, builder.build(), FIFTY_FIVE, TimeUnit.DAYS);
          dataRetentionRules.setRules(Collections.singletonList(rule));
          dataRetentionRulesService.writeDocument(dataRetentionRules);
      }
  
      private DataRetentionRule createRule(final int num, final ExpressionOperator expression, final int age, final TimeUnit timeUnit) {
          return new DataRetentionRule(num, System.currentTimeMillis(), "rule " + num, true, expression, age, timeUnit, false);
      }
  }
  