This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new 6eec8f421 [test] Unify tests and rename to ExpireSnapshotsTest
6eec8f421 is described below
commit 6eec8f421a807e687c46bbb362020720ddf794d8
Author: Jingsong <[email protected]>
AuthorDate: Mon Apr 1 12:11:38 2024 +0800
[test] Unify tests and rename to ExpireSnapshotsTest
---
...oreExpireTest.java => ExpireSnapshotsTest.java} | 218 +++++++++++++++++++--
.../apache/paimon/operation/FileDeletionTest.java | 2 +-
.../paimon/operation/FileStoreExpireTestBase.java | 130 ------------
.../operation/UncleanedFileStoreExpireTest.java | 129 ------------
4 files changed, 205 insertions(+), 274 deletions(-)
diff --git
a/paimon-core/src/test/java/org/apache/paimon/operation/CleanedFileStoreExpireTest.java
b/paimon-core/src/test/java/org/apache/paimon/operation/ExpireSnapshotsTest.java
similarity index 53%
rename from
paimon-core/src/test/java/org/apache/paimon/operation/CleanedFileStoreExpireTest.java
rename to
paimon-core/src/test/java/org/apache/paimon/operation/ExpireSnapshotsTest.java
index 02e3ab9e3..2343aa462 100644
---
a/paimon-core/src/test/java/org/apache/paimon/operation/CleanedFileStoreExpireTest.java
+++
b/paimon-core/src/test/java/org/apache/paimon/operation/ExpireSnapshotsTest.java
@@ -18,41 +18,155 @@
package org.apache.paimon.operation;
+import org.apache.paimon.CoreOptions;
import org.apache.paimon.KeyValue;
+import org.apache.paimon.Snapshot;
+import org.apache.paimon.TestFileStore;
+import org.apache.paimon.TestKeyValueGenerator;
import org.apache.paimon.data.BinaryRow;
import org.apache.paimon.data.Timestamp;
+import org.apache.paimon.fs.FileIO;
import org.apache.paimon.fs.Path;
import org.apache.paimon.fs.local.LocalFileIO;
import org.apache.paimon.io.DataFileMeta;
import org.apache.paimon.manifest.FileKind;
import org.apache.paimon.manifest.ManifestEntry;
+import org.apache.paimon.mergetree.compact.DeduplicateMergeFunction;
+import org.apache.paimon.schema.Schema;
+import org.apache.paimon.schema.SchemaManager;
import org.apache.paimon.table.ExpireSnapshots;
import org.apache.paimon.table.ExpireSnapshotsImpl;
import org.apache.paimon.utils.RecordWriter;
import org.apache.paimon.utils.SnapshotManager;
+import org.apache.paimon.utils.TagManager;
-import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
+import java.util.stream.Collectors;
+import static java.util.Objects.requireNonNull;
import static org.apache.paimon.data.BinaryRow.EMPTY_ROW;
import static org.assertj.core.api.Assertions.assertThat;
-/**
- * Tests for {@link ExpireSnapshotsImpl}. After expiration, only useful files
should be retained.
- */
-public class CleanedFileStoreExpireTest extends FileStoreExpireTestBase {
+/** Base test class for {@link ExpireSnapshotsImpl}. */
+public class ExpireSnapshotsTest {
+
+ protected final FileIO fileIO = new LocalFileIO();
+ protected TestKeyValueGenerator gen;
+ @TempDir java.nio.file.Path tempDir;
+ protected TestFileStore store;
+ protected SnapshotManager snapshotManager;
+
+ @BeforeEach
+ public void beforeEach() throws Exception {
+ gen = new TestKeyValueGenerator();
+ store = createStore();
+ snapshotManager = store.snapshotManager();
+ SchemaManager schemaManager = new SchemaManager(fileIO, new
Path(tempDir.toUri()));
+ schemaManager.createTable(
+ new Schema(
+ TestKeyValueGenerator.DEFAULT_ROW_TYPE.getFields(),
+
TestKeyValueGenerator.DEFAULT_PART_TYPE.getFieldNames(),
+ TestKeyValueGenerator.getPrimaryKeys(
+
TestKeyValueGenerator.GeneratorMode.MULTI_PARTITIONED),
+ Collections.emptyMap(),
+ null));
+ }
- @AfterEach
- public void afterEach() throws IOException {
- store.assertCleaned();
+ @Test
+ public void testExpireWithMissingFiles() throws Exception {
+ ExpireSnapshots expire = store.newExpire(1, 1, 1);
+
+ List<KeyValue> allData = new ArrayList<>();
+ List<Integer> snapshotPositions = new ArrayList<>();
+ commit(5, allData, snapshotPositions);
+
+ int latestSnapshotId =
requireNonNull(snapshotManager.latestSnapshotId()).intValue();
+ Set<Path> filesInUse = store.getFilesInUse(latestSnapshotId);
+ List<Path> unusedFileList =
+ Files.walk(Paths.get(tempDir.toString()))
+ .filter(Files::isRegularFile)
+ .filter(p ->
!p.getFileName().toString().startsWith("snapshot"))
+ .filter(p ->
!p.getFileName().toString().startsWith("schema"))
+ .map(p -> new Path(p.toString()))
+ .filter(p -> !filesInUse.contains(p))
+ .collect(Collectors.toList());
+
+ // shuffle list
+ ThreadLocalRandom random = ThreadLocalRandom.current();
+ for (int i = unusedFileList.size() - 1; i > 0; i--) {
+ int j = random.nextInt(i + 1);
+ Collections.swap(unusedFileList, i, j);
+ }
+
+ // delete some unused files
+ int numFilesToDelete = random.nextInt(unusedFileList.size());
+ for (int i = 0; i < numFilesToDelete; i++) {
+ fileIO.deleteQuietly(unusedFileList.get(i));
+ }
+
+ expire.expire();
+
+ for (int i = 1; i < latestSnapshotId; i++) {
+ assertThat(snapshotManager.snapshotExists(i)).isFalse();
+ }
+ assertThat(snapshotManager.snapshotExists(latestSnapshotId)).isTrue();
+ assertSnapshot(latestSnapshotId, allData, snapshotPositions);
+ }
+
+ @Test
+ public void testMixedSnapshotAndTagDeletion() throws Exception {
+ List<KeyValue> allData = new ArrayList<>();
+ List<Integer> snapshotPositions = new ArrayList<>();
+ ThreadLocalRandom random = ThreadLocalRandom.current();
+
+ commit(random.nextInt(10) + 30, allData, snapshotPositions);
+ int latestSnapshotId =
requireNonNull(snapshotManager.latestSnapshotId()).intValue();
+ TagManager tagManager = store.newTagManager();
+
+ // create tags for each snapshot
+ for (int id = 1; id <= latestSnapshotId; id++) {
+ Snapshot snapshot = snapshotManager.snapshot(id);
+ tagManager.createTag(snapshot, "tag" + id,
Collections.emptyList());
+ }
+
+ // randomly expire snapshots
+ int expired = random.nextInt(latestSnapshotId / 2) + 1;
+ int retained = latestSnapshotId - expired;
+ store.newExpire(retained, retained, Long.MAX_VALUE).expire();
+
+ // randomly delete tags
+ for (int id = 1; id <= latestSnapshotId; id++) {
+ if (random.nextBoolean()) {
+ tagManager.deleteTag(
+ "tag" + id,
+ store.newTagDeletion(),
+ snapshotManager,
+ Collections.emptyList());
+ }
+ }
+
+ // check snapshots and tags
+ Set<Snapshot> allSnapshots = new HashSet<>();
+ snapshotManager.snapshots().forEachRemaining(allSnapshots::add);
+ allSnapshots.addAll(tagManager.taggedSnapshots());
+
+ for (Snapshot snapshot : allSnapshots) {
+ assertSnapshot(snapshot, allData, snapshotPositions);
+ }
}
@Test
@@ -97,14 +211,18 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
assertThat(fileIO.exists(myDataFile)).isFalse();
assertThat(fileIO.exists(extra1)).isFalse();
assertThat(fileIO.exists(extra2)).isFalse();
+
+ store.assertCleaned();
}
@Test
- public void testNoSnapshot() {
+ public void testNoSnapshot() throws IOException {
ExpireSnapshots expire = store.newExpire(1, 3, Long.MAX_VALUE);
expire.expire();
assertThat(snapshotManager.latestSnapshotId()).isNull();
+
+ store.assertCleaned();
}
@Test
@@ -112,7 +230,7 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
List<KeyValue> allData = new ArrayList<>();
List<Integer> snapshotPositions = new ArrayList<>();
commit(2, allData, snapshotPositions);
- int latestSnapshotId = snapshotManager.latestSnapshotId().intValue();
+ int latestSnapshotId =
requireNonNull(snapshotManager.latestSnapshotId()).intValue();
ExpireSnapshots expire = store.newExpire(1, latestSnapshotId + 1,
Long.MAX_VALUE);
expire.expire();
@@ -120,6 +238,8 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
assertThat(snapshotManager.snapshotExists(i)).isTrue();
assertSnapshot(i, allData, snapshotPositions);
}
+
+ store.assertCleaned();
}
@Test
@@ -127,7 +247,7 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
List<KeyValue> allData = new ArrayList<>();
List<Integer> snapshotPositions = new ArrayList<>();
commit(5, allData, snapshotPositions);
- int latestSnapshotId = snapshotManager.latestSnapshotId().intValue();
+ int latestSnapshotId =
requireNonNull(snapshotManager.latestSnapshotId()).intValue();
ExpireSnapshots expire = store.newExpire(1, Integer.MAX_VALUE,
Long.MAX_VALUE);
expire.expire();
@@ -135,6 +255,8 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
assertThat(snapshotManager.snapshotExists(i)).isTrue();
assertSnapshot(i, allData, snapshotPositions);
}
+
+ store.assertCleaned();
}
@Test
@@ -145,7 +267,7 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
List<KeyValue> allData = new ArrayList<>();
List<Integer> snapshotPositions = new ArrayList<>();
commit(numRetainedMin + random.nextInt(5), allData, snapshotPositions);
- int latestSnapshotId = snapshotManager.latestSnapshotId().intValue();
+ int latestSnapshotId =
requireNonNull(snapshotManager.latestSnapshotId()).intValue();
Thread.sleep(100);
ExpireSnapshots expire = store.newExpire(numRetainedMin,
Integer.MAX_VALUE, 1);
expire.expire();
@@ -157,6 +279,8 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
assertThat(snapshotManager.snapshotExists(i)).isTrue();
assertSnapshot(i, allData, snapshotPositions);
}
+
+ store.assertCleaned();
}
@Test
@@ -169,7 +293,7 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
commit(ThreadLocalRandom.current().nextInt(5) + 1, allData,
snapshotPositions);
expire.expire();
- int latestSnapshotId =
snapshotManager.latestSnapshotId().intValue();
+ int latestSnapshotId =
requireNonNull(snapshotManager.latestSnapshotId()).intValue();
for (int j = 1; j <= latestSnapshotId; j++) {
if (j > latestSnapshotId - 3) {
assertThat(snapshotManager.snapshotExists(j)).isTrue();
@@ -193,6 +317,8 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
fileIO.delete(earliest, false);
assertThat(snapshotManager.earliestSnapshotId()).isEqualTo(earliestId);
+
+ store.assertCleaned();
}
@Test
@@ -209,7 +335,7 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
expire.olderThanMills(expireMillis - 1000).expire();
expire.olderThanMills(expireMillis - 1000).expire();
- int latestSnapshotId = snapshotManager.latestSnapshotId().intValue();
+ int latestSnapshotId =
requireNonNull(snapshotManager.latestSnapshotId()).intValue();
for (int i = 1; i <= latestSnapshotId; i++) {
if (snapshotManager.snapshotExists(i)) {
assertThat(snapshotManager.snapshot(i).timeMillis())
@@ -217,6 +343,8 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
assertSnapshot(i, allData, snapshotPositions);
}
}
+
+ store.assertCleaned();
}
@Test
@@ -258,5 +386,67 @@ public class CleanedFileStoreExpireTest extends
FileStoreExpireTestBase {
ExpireSnapshots expire = store.newExpire(1, 1, Long.MAX_VALUE);
expire.expire();
FileStoreTestUtils.assertPathExists(fileIO, dataFilePath2);
+
+ store.assertCleaned();
+ }
+
+ private TestFileStore createStore() {
+ ThreadLocalRandom random = ThreadLocalRandom.current();
+
+ CoreOptions.ChangelogProducer changelogProducer;
+ if (random.nextBoolean()) {
+ changelogProducer = CoreOptions.ChangelogProducer.INPUT;
+ } else {
+ changelogProducer = CoreOptions.ChangelogProducer.NONE;
+ }
+
+ return new TestFileStore.Builder(
+ "avro",
+ tempDir.toString(),
+ 1,
+ TestKeyValueGenerator.DEFAULT_PART_TYPE,
+ TestKeyValueGenerator.KEY_TYPE,
+ TestKeyValueGenerator.DEFAULT_ROW_TYPE,
+
TestKeyValueGenerator.TestKeyValueFieldsExtractor.EXTRACTOR,
+ DeduplicateMergeFunction.factory(),
+ null)
+ .changelogProducer(changelogProducer)
+ .build();
+ }
+
+ protected void commit(int numCommits, List<KeyValue> allData,
List<Integer> snapshotPositions)
+ throws Exception {
+ for (int i = 0; i < numCommits; i++) {
+ int numRecords = ThreadLocalRandom.current().nextInt(100) + 1;
+ List<KeyValue> data = new ArrayList<>();
+ for (int j = 0; j < numRecords; j++) {
+ data.add(gen.next());
+ }
+ allData.addAll(data);
+ List<Snapshot> snapshots = store.commitData(data,
gen::getPartition, kv -> 0);
+ for (int j = 0; j < snapshots.size(); j++) {
+ snapshotPositions.add(allData.size());
+ }
+ }
+ }
+
+ protected void assertSnapshot(
+ int snapshotId, List<KeyValue> allData, List<Integer>
snapshotPositions)
+ throws Exception {
+ assertSnapshot(snapshotManager.snapshot(snapshotId), allData,
snapshotPositions);
+ }
+
+ protected void assertSnapshot(
+ Snapshot snapshot, List<KeyValue> allData, List<Integer>
snapshotPositions)
+ throws Exception {
+ int snapshotId = (int) snapshot.id();
+ Map<BinaryRow, BinaryRow> expected =
+ store.toKvMap(allData.subList(0,
snapshotPositions.get(snapshotId - 1)));
+ List<KeyValue> actualKvs =
+ store.readKvsFromManifestEntries(
+ store.newScan().withSnapshot(snapshot).plan().files(),
false);
+ gen.sort(actualKvs);
+ Map<BinaryRow, BinaryRow> actual = store.toKvMap(actualKvs);
+ assertThat(actual).isEqualTo(expected);
}
}
diff --git
a/paimon-core/src/test/java/org/apache/paimon/operation/FileDeletionTest.java
b/paimon-core/src/test/java/org/apache/paimon/operation/FileDeletionTest.java
index ec73eb317..94c26c455 100644
---
a/paimon-core/src/test/java/org/apache/paimon/operation/FileDeletionTest.java
+++
b/paimon-core/src/test/java/org/apache/paimon/operation/FileDeletionTest.java
@@ -70,7 +70,7 @@ import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for file deletion when expiring snapshot and deleting tag. It also
tests that after
* expiration, empty data file directories (buckets and partitions) are
deleted. It didn't extend
- * {@link FileStoreExpireTestBase} because there are not too many codes can be
reused.
+ * {@link ExpireSnapshotsTest} because there are not too many codes can be
reused.
*/
public class FileDeletionTest {
diff --git
a/paimon-core/src/test/java/org/apache/paimon/operation/FileStoreExpireTestBase.java
b/paimon-core/src/test/java/org/apache/paimon/operation/FileStoreExpireTestBase.java
deleted file mode 100644
index 5ebe76ed6..000000000
---
a/paimon-core/src/test/java/org/apache/paimon/operation/FileStoreExpireTestBase.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.paimon.operation;
-
-import org.apache.paimon.CoreOptions;
-import org.apache.paimon.KeyValue;
-import org.apache.paimon.Snapshot;
-import org.apache.paimon.TestFileStore;
-import org.apache.paimon.TestKeyValueGenerator;
-import org.apache.paimon.data.BinaryRow;
-import org.apache.paimon.fs.FileIO;
-import org.apache.paimon.fs.Path;
-import org.apache.paimon.fs.local.LocalFileIO;
-import org.apache.paimon.mergetree.compact.DeduplicateMergeFunction;
-import org.apache.paimon.schema.Schema;
-import org.apache.paimon.schema.SchemaManager;
-import org.apache.paimon.utils.SnapshotManager;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.io.TempDir;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ThreadLocalRandom;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-/** Base test class for {@link FileStoreExpireImpl}. */
-public abstract class FileStoreExpireTestBase {
-
- protected final FileIO fileIO = new LocalFileIO();
- protected TestKeyValueGenerator gen;
- @TempDir java.nio.file.Path tempDir;
- protected TestFileStore store;
- protected SnapshotManager snapshotManager;
-
- @BeforeEach
- public void beforeEach() throws Exception {
- gen = new TestKeyValueGenerator();
- store = createStore();
- snapshotManager = store.snapshotManager();
- SchemaManager schemaManager = new SchemaManager(fileIO, new
Path(tempDir.toUri()));
- schemaManager.createTable(
- new Schema(
- TestKeyValueGenerator.DEFAULT_ROW_TYPE.getFields(),
-
TestKeyValueGenerator.DEFAULT_PART_TYPE.getFieldNames(),
- TestKeyValueGenerator.getPrimaryKeys(
-
TestKeyValueGenerator.GeneratorMode.MULTI_PARTITIONED),
- Collections.emptyMap(),
- null));
- }
-
- private TestFileStore createStore() {
- ThreadLocalRandom random = ThreadLocalRandom.current();
-
- CoreOptions.ChangelogProducer changelogProducer;
- if (random.nextBoolean()) {
- changelogProducer = CoreOptions.ChangelogProducer.INPUT;
- } else {
- changelogProducer = CoreOptions.ChangelogProducer.NONE;
- }
-
- return new TestFileStore.Builder(
- "avro",
- tempDir.toString(),
- 1,
- TestKeyValueGenerator.DEFAULT_PART_TYPE,
- TestKeyValueGenerator.KEY_TYPE,
- TestKeyValueGenerator.DEFAULT_ROW_TYPE,
-
TestKeyValueGenerator.TestKeyValueFieldsExtractor.EXTRACTOR,
- DeduplicateMergeFunction.factory(),
- null)
- .changelogProducer(changelogProducer)
- .build();
- }
-
- protected void commit(int numCommits, List<KeyValue> allData,
List<Integer> snapshotPositions)
- throws Exception {
- for (int i = 0; i < numCommits; i++) {
- int numRecords = ThreadLocalRandom.current().nextInt(100) + 1;
- List<KeyValue> data = new ArrayList<>();
- for (int j = 0; j < numRecords; j++) {
- data.add(gen.next());
- }
- allData.addAll(data);
- List<Snapshot> snapshots = store.commitData(data,
gen::getPartition, kv -> 0);
- for (int j = 0; j < snapshots.size(); j++) {
- snapshotPositions.add(allData.size());
- }
- }
- }
-
- protected void assertSnapshot(
- int snapshotId, List<KeyValue> allData, List<Integer>
snapshotPositions)
- throws Exception {
- assertSnapshot(snapshotManager.snapshot(snapshotId), allData,
snapshotPositions);
- }
-
- protected void assertSnapshot(
- Snapshot snapshot, List<KeyValue> allData, List<Integer>
snapshotPositions)
- throws Exception {
- int snapshotId = (int) snapshot.id();
- Map<BinaryRow, BinaryRow> expected =
- store.toKvMap(allData.subList(0,
snapshotPositions.get(snapshotId - 1)));
- List<KeyValue> actualKvs =
- store.readKvsFromManifestEntries(
- store.newScan().withSnapshot(snapshot).plan().files(),
false);
- gen.sort(actualKvs);
- Map<BinaryRow, BinaryRow> actual = store.toKvMap(actualKvs);
- assertThat(actual).isEqualTo(expected);
- }
-}
diff --git
a/paimon-core/src/test/java/org/apache/paimon/operation/UncleanedFileStoreExpireTest.java
b/paimon-core/src/test/java/org/apache/paimon/operation/UncleanedFileStoreExpireTest.java
deleted file mode 100644
index 9f5ccb81c..000000000
---
a/paimon-core/src/test/java/org/apache/paimon/operation/UncleanedFileStoreExpireTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.paimon.operation;
-
-import org.apache.paimon.KeyValue;
-import org.apache.paimon.Snapshot;
-import org.apache.paimon.fs.Path;
-import org.apache.paimon.table.ExpireSnapshots;
-import org.apache.paimon.utils.TagManager;
-
-import org.junit.jupiter.api.Test;
-
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ThreadLocalRandom;
-import java.util.stream.Collectors;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-/**
- * Tests for {@link ExpireSnapshots}. Some files not in use may still remain
after the test due to
- * the testing methods.
- */
-public class UncleanedFileStoreExpireTest extends FileStoreExpireTestBase {
-
- @Test
- public void testExpireWithMissingFiles() throws Exception {
- ExpireSnapshots expire = store.newExpire(1, 1, 1);
-
- List<KeyValue> allData = new ArrayList<>();
- List<Integer> snapshotPositions = new ArrayList<>();
- commit(5, allData, snapshotPositions);
-
- int latestSnapshotId = snapshotManager.latestSnapshotId().intValue();
- Set<Path> filesInUse = store.getFilesInUse(latestSnapshotId);
- List<Path> unusedFileList =
- Files.walk(Paths.get(tempDir.toString()))
- .filter(Files::isRegularFile)
- .filter(p ->
!p.getFileName().toString().startsWith("snapshot"))
- .filter(p ->
!p.getFileName().toString().startsWith("schema"))
- .map(p -> new Path(p.toString()))
- .filter(p -> !filesInUse.contains(p))
- .collect(Collectors.toList());
-
- // shuffle list
- ThreadLocalRandom random = ThreadLocalRandom.current();
- for (int i = unusedFileList.size() - 1; i > 0; i--) {
- int j = random.nextInt(i + 1);
- Collections.swap(unusedFileList, i, j);
- }
-
- // delete some unused files
- int numFilesToDelete = random.nextInt(unusedFileList.size());
- for (int i = 0; i < numFilesToDelete; i++) {
- fileIO.deleteQuietly(unusedFileList.get(i));
- }
-
- expire.expire();
-
- for (int i = 1; i < latestSnapshotId; i++) {
- assertThat(snapshotManager.snapshotExists(i)).isFalse();
- }
- assertThat(snapshotManager.snapshotExists(latestSnapshotId)).isTrue();
- assertSnapshot(latestSnapshotId, allData, snapshotPositions);
- }
-
- @Test
- public void testMixedSnapshotAndTagDeletion() throws Exception {
- List<KeyValue> allData = new ArrayList<>();
- List<Integer> snapshotPositions = new ArrayList<>();
- ThreadLocalRandom random = ThreadLocalRandom.current();
-
- commit(random.nextInt(10) + 30, allData, snapshotPositions);
- int latestSnapshotId = snapshotManager.latestSnapshotId().intValue();
- TagManager tagManager = store.newTagManager();
-
- // create tags for each snapshot
- for (int id = 1; id <= latestSnapshotId; id++) {
- Snapshot snapshot = snapshotManager.snapshot(id);
- tagManager.createTag(snapshot, "tag" + id,
Collections.emptyList());
- }
-
- // randomly expire snapshots
- int expired = random.nextInt(latestSnapshotId / 2) + 1;
- int retained = latestSnapshotId - expired;
- store.newExpire(retained, retained, Long.MAX_VALUE).expire();
-
- // randomly delete tags
- for (int id = 1; id <= latestSnapshotId; id++) {
- if (random.nextBoolean()) {
- tagManager.deleteTag(
- "tag" + id,
- store.newTagDeletion(),
- snapshotManager,
- Collections.emptyList());
- }
- }
-
- // check snapshots and tags
- Set<Snapshot> allSnapshots = new HashSet<>();
- snapshotManager.snapshots().forEachRemaining(allSnapshots::add);
- allSnapshots.addAll(tagManager.taggedSnapshots());
-
- for (Snapshot snapshot : allSnapshots) {
- assertSnapshot(snapshot, allData, snapshotPositions);
- }
- }
-}