Skip to content

Commit 5735e38

Browse files
DaveCTurnercbuescher
authored andcommitted
Extract BlobStoreCorruptionUtils (elastic#112229)
Makes these utility methods available to other test suites (to be added in future PRs). Relates elastic#111954
1 parent 7e27cc1 commit 5735e38

File tree

2 files changed

+90
-67
lines changed

2 files changed

+90
-67
lines changed

server/src/internalClusterTest/java/org/elasticsearch/repositories/blobstore/BlobStoreCorruptionIT.java

Lines changed: 1 addition & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
package org.elasticsearch.repositories.blobstore;
1010

11-
import org.apache.lucene.tests.mockfile.ExtrasFS;
1211
import org.elasticsearch.ElasticsearchException;
1312
import org.elasticsearch.action.ActionListener;
1413
import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotResponse;
@@ -23,18 +22,10 @@
2322
import org.elasticsearch.repositories.fs.FsRepository;
2423
import org.elasticsearch.snapshots.AbstractSnapshotIntegTestCase;
2524
import org.elasticsearch.snapshots.SnapshotState;
26-
import org.elasticsearch.test.ESTestCase;
2725
import org.elasticsearch.test.hamcrest.ElasticsearchAssertions;
2826
import org.junit.Before;
2927

30-
import java.io.IOException;
31-
import java.nio.file.FileVisitResult;
32-
import java.nio.file.Files;
33-
import java.nio.file.Path;
34-
import java.nio.file.SimpleFileVisitor;
35-
import java.nio.file.attribute.BasicFileAttributes;
3628
import java.util.ArrayList;
37-
import java.util.Base64;
3829
import java.util.List;
3930

4031
public class BlobStoreCorruptionIT extends AbstractSnapshotIntegTestCase {
@@ -57,7 +48,7 @@ public void testCorruptionDetection() throws Exception {
5748
flushAndRefresh(indexName);
5849
createSnapshot(repositoryName, snapshotName, List.of(indexName));
5950

60-
final var corruptedFile = corruptRandomFile(repositoryRootPath);
51+
final var corruptedFile = BlobStoreCorruptionUtils.corruptRandomFile(repositoryRootPath);
6152
final var corruptedFileType = RepositoryFileType.getRepositoryFileType(repositoryRootPath, corruptedFile);
6253
final var corruptionDetectors = new ArrayList<CheckedConsumer<ActionListener<Exception>, ?>>();
6354

@@ -126,61 +117,4 @@ public void testCorruptionDetection() throws Exception {
126117
logger.info(Strings.format("--> corrupted [%s] and caught exception", corruptedFile), exception);
127118
}
128119
}
129-
130-
private static Path corruptRandomFile(Path repositoryRootPath) throws IOException {
131-
final var corruptedFileType = getRandomCorruptibleFileType();
132-
final var corruptedFile = getRandomFileToCorrupt(repositoryRootPath, corruptedFileType);
133-
if (randomBoolean()) {
134-
logger.info("--> deleting [{}]", corruptedFile);
135-
Files.delete(corruptedFile);
136-
} else {
137-
corruptFileContents(corruptedFile);
138-
}
139-
return corruptedFile;
140-
}
141-
142-
private static void corruptFileContents(Path fileToCorrupt) throws IOException {
143-
final var oldFileContents = Files.readAllBytes(fileToCorrupt);
144-
logger.info("--> contents of [{}] before corruption: [{}]", fileToCorrupt, Base64.getEncoder().encodeToString(oldFileContents));
145-
final byte[] newFileContents = new byte[randomBoolean() ? oldFileContents.length : between(0, oldFileContents.length)];
146-
System.arraycopy(oldFileContents, 0, newFileContents, 0, newFileContents.length);
147-
if (newFileContents.length == oldFileContents.length) {
148-
final var corruptionPosition = between(0, newFileContents.length - 1);
149-
newFileContents[corruptionPosition] = randomValueOtherThan(oldFileContents[corruptionPosition], ESTestCase::randomByte);
150-
logger.info(
151-
"--> updating byte at position [{}] from [{}] to [{}]",
152-
corruptionPosition,
153-
oldFileContents[corruptionPosition],
154-
newFileContents[corruptionPosition]
155-
);
156-
} else {
157-
logger.info("--> truncating file from length [{}] to length [{}]", oldFileContents.length, newFileContents.length);
158-
}
159-
Files.write(fileToCorrupt, newFileContents);
160-
logger.info("--> contents of [{}] after corruption: [{}]", fileToCorrupt, Base64.getEncoder().encodeToString(newFileContents));
161-
}
162-
163-
private static RepositoryFileType getRandomCorruptibleFileType() {
164-
return randomValueOtherThanMany(
165-
// these blob types do not have reliable corruption detection, so we must skip them
166-
t -> t == RepositoryFileType.ROOT_INDEX_N || t == RepositoryFileType.ROOT_INDEX_LATEST,
167-
() -> randomFrom(RepositoryFileType.values())
168-
);
169-
}
170-
171-
private static Path getRandomFileToCorrupt(Path repositoryRootPath, RepositoryFileType corruptedFileType) throws IOException {
172-
final var corruptibleFiles = new ArrayList<Path>();
173-
Files.walkFileTree(repositoryRootPath, new SimpleFileVisitor<>() {
174-
@Override
175-
public FileVisitResult visitFile(Path filePath, BasicFileAttributes attrs) throws IOException {
176-
if (ExtrasFS.isExtra(filePath.getFileName().toString()) == false
177-
&& RepositoryFileType.getRepositoryFileType(repositoryRootPath, filePath) == corruptedFileType) {
178-
corruptibleFiles.add(filePath);
179-
}
180-
return super.visitFile(filePath, attrs);
181-
}
182-
});
183-
return randomFrom(corruptibleFiles);
184-
}
185-
186120
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
package org.elasticsearch.repositories.blobstore;
10+
11+
import org.apache.lucene.tests.mockfile.ExtrasFS;
12+
import org.elasticsearch.logging.LogManager;
13+
import org.elasticsearch.logging.Logger;
14+
import org.elasticsearch.test.ESTestCase;
15+
16+
import java.io.IOException;
17+
import java.nio.file.FileVisitResult;
18+
import java.nio.file.Files;
19+
import java.nio.file.Path;
20+
import java.nio.file.SimpleFileVisitor;
21+
import java.nio.file.attribute.BasicFileAttributes;
22+
import java.util.ArrayList;
23+
import java.util.Base64;
24+
25+
import static org.elasticsearch.test.ESTestCase.between;
26+
import static org.elasticsearch.test.ESTestCase.randomBoolean;
27+
import static org.elasticsearch.test.ESTestCase.randomFrom;
28+
import static org.elasticsearch.test.ESTestCase.randomValueOtherThan;
29+
import static org.elasticsearch.test.ESTestCase.randomValueOtherThanMany;
30+
31+
public class BlobStoreCorruptionUtils {
32+
private static final Logger logger = LogManager.getLogger(BlobStoreCorruptionUtils.class);
33+
34+
public static Path corruptRandomFile(Path repositoryRootPath) throws IOException {
35+
final var corruptedFileType = getRandomCorruptibleFileType();
36+
final var corruptedFile = getRandomFileToCorrupt(repositoryRootPath, corruptedFileType);
37+
if (randomBoolean()) {
38+
logger.info("--> deleting [{}]", corruptedFile);
39+
Files.delete(corruptedFile);
40+
} else {
41+
corruptFileContents(corruptedFile);
42+
}
43+
return corruptedFile;
44+
}
45+
46+
public static void corruptFileContents(Path fileToCorrupt) throws IOException {
47+
final var oldFileContents = Files.readAllBytes(fileToCorrupt);
48+
logger.info("--> contents of [{}] before corruption: [{}]", fileToCorrupt, Base64.getEncoder().encodeToString(oldFileContents));
49+
final byte[] newFileContents = new byte[randomBoolean() ? oldFileContents.length : between(0, oldFileContents.length)];
50+
System.arraycopy(oldFileContents, 0, newFileContents, 0, newFileContents.length);
51+
if (newFileContents.length == oldFileContents.length) {
52+
final var corruptionPosition = between(0, newFileContents.length - 1);
53+
newFileContents[corruptionPosition] = randomValueOtherThan(oldFileContents[corruptionPosition], ESTestCase::randomByte);
54+
logger.info(
55+
"--> updating byte at position [{}] from [{}] to [{}]",
56+
corruptionPosition,
57+
oldFileContents[corruptionPosition],
58+
newFileContents[corruptionPosition]
59+
);
60+
} else {
61+
logger.info("--> truncating file from length [{}] to length [{}]", oldFileContents.length, newFileContents.length);
62+
}
63+
Files.write(fileToCorrupt, newFileContents);
64+
logger.info("--> contents of [{}] after corruption: [{}]", fileToCorrupt, Base64.getEncoder().encodeToString(newFileContents));
65+
}
66+
67+
public static RepositoryFileType getRandomCorruptibleFileType() {
68+
return randomValueOtherThanMany(
69+
// these blob types do not have reliable corruption detection, so we must skip them
70+
t -> t == RepositoryFileType.ROOT_INDEX_N || t == RepositoryFileType.ROOT_INDEX_LATEST,
71+
() -> randomFrom(RepositoryFileType.values())
72+
);
73+
}
74+
75+
public static Path getRandomFileToCorrupt(Path repositoryRootPath, RepositoryFileType corruptedFileType) throws IOException {
76+
final var corruptibleFiles = new ArrayList<Path>();
77+
Files.walkFileTree(repositoryRootPath, new SimpleFileVisitor<>() {
78+
@Override
79+
public FileVisitResult visitFile(Path filePath, BasicFileAttributes attrs) throws IOException {
80+
if (ExtrasFS.isExtra(filePath.getFileName().toString()) == false
81+
&& RepositoryFileType.getRepositoryFileType(repositoryRootPath, filePath) == corruptedFileType) {
82+
corruptibleFiles.add(filePath);
83+
}
84+
return super.visitFile(filePath, attrs);
85+
}
86+
});
87+
return randomFrom(corruptibleFiles);
88+
}
89+
}

0 commit comments

Comments
 (0)