Fix addBackcompatIndexes.py to properly generate missing versions (#13095)

In #13046 several changes broke the addBackcompatIndexes.py script
to properly add and test the unreleased version. This updates the
script to again properly add the new version.

Closes #13094

Co-authored-by: Dawid Weiss <dawid.weiss@carrotsearch.com>
This commit is contained in:
Simon Willnauer 2024-02-14 21:43:17 +01:00
parent 444d816622
commit c9e4434cc3
9 changed files with 271 additions and 334 deletions

View File

@ -96,16 +96,15 @@ def create_and_add_index(source, indextype, index_version, current_version, temp
scriptutil.run('rm -rf %s' % bc_index_dir)
print('done')
def update_backcompat_tests(types, index_version, current_version):
print(' adding new indexes %s to backcompat tests...' % types, end='', flush=True)
def update_backcompat_tests(index_version, current_version):
print(' adding new indexes to backcompat tests...', end='', flush=True)
module = 'lucene/backward-codecs'
filename = '%s/src/test/org/apache/lucene/backward_index/TestGenerateBwcIndices.java' % module
filename = None
if not current_version.is_back_compat_with(index_version):
matcher = re.compile(r'final String\[\] unsupportedNames = {|};')
elif 'sorted' in types:
matcher = re.compile(r'static final String\[\] oldSortedNames = {|};')
filename = '%s/src/test/org/apache/lucene/backward_index/unsupported_versions.txt' % module
else:
matcher = re.compile(r'static final String\[\] oldNames = {|};')
filename = '%s/src/test/org/apache/lucene/backward_index/versions.txt' % module
strip_dash_suffix_re = re.compile(r'-.*')
@ -114,53 +113,25 @@ def update_backcompat_tests(types, index_version, current_version):
x = re.sub(strip_dash_suffix_re, '', x) # remove the -suffix if any
return scriptutil.Version.parse(x)
class Edit(object):
start = None
def __call__(self, buffer, match, line):
if self.start:
# find where this version should exist
i = len(buffer) - 1
previous_version_exists = not ('};' in line and buffer[-1].strip().endswith("{"))
if previous_version_exists: # Only look if there is a version here
v = find_version(buffer[i])
while i >= self.start and v.on_or_after(index_version):
i -= 1
v = find_version(buffer[i])
i += 1 # readjust since we skipped past by 1
def edit(buffer, match, line):
v = find_version(line)
changed = False
if v.on_or_after(index_version):
if not index_version.on_or_after(v):
buffer.append(('%s\n') % index_version)
changed = True
buffer.append(line)
return changed
# unfortunately python doesn't have a range remove from list...
# here we want to remove any previous references to the version we are adding
while i < len(buffer) and index_version.on_or_after(find_version(buffer[i])):
buffer.pop(i)
if i == len(buffer) and previous_version_exists and not buffer[-1].strip().endswith(","):
# add comma
buffer[-1] = buffer[-1].rstrip() + ",\n"
if previous_version_exists:
last = buffer[-1]
spaces = ' ' * (len(last) - len(last.lstrip()))
else:
spaces = ' '
for (j, t) in enumerate(types):
if t == 'sorted':
newline = spaces + ('"sorted.%s"') % index_version
else:
newline = spaces + ('"%s-%s"' % (index_version, t))
if j < len(types) - 1 or i < len(buffer):
newline += ','
buffer.insert(i, newline + '\n')
i += 1
buffer.append(line)
return True
if 'Names = {' in line:
self.start = len(buffer) # location of first index name
buffer.append(line)
return False
def append(buffer, changed):
if changed:
return changed
if not buffer[len(buffer)-1].endswith('\n'):
buffer.append('\n')
buffer.append(('%s\n') % index_version)
return True
changed = scriptutil.update_file(filename, matcher, Edit())
changed = scriptutil.update_file(filename, re.compile(r'.*'), edit, append)
print('done' if changed else 'uptodate')
def check_backcompat_tests():
@ -251,9 +222,8 @@ def main():
print ('\nMANUAL UPDATE REQUIRED: edit TestGenerateBwcIndices to enable moreterms, dvupdates, and empty index testing')
print('\nAdding backwards compatibility tests')
update_backcompat_tests(['cfs', 'nocfs'], c.version, current_version)
if should_make_sorted:
update_backcompat_tests(['sorted'], c.version, current_version)
update_backcompat_tests(c.version, current_version)
print('\nTesting changes')
check_backcompat_tests()

View File

@ -88,7 +88,7 @@ def run(cmd, cwd=None):
raise e
return output.decode('utf-8')
def update_file(filename, line_re, edit):
def update_file(filename, line_re, edit, append=None):
infile = open(filename, 'r')
buffer = []
@ -102,6 +102,8 @@ def update_file(filename, line_re, edit):
return False
continue
buffer.append(line)
if append:
changed = append(buffer, changed) # in the case did not change in edit but have an append function
if not changed:
raise Exception('Could not find %s in %s' % (line_re, filename))
with open(filename, 'w') as f:

View File

@ -19,8 +19,10 @@ package org.apache.lucene.backward_index;
import com.carrotsearch.randomizedtesting.annotations.Name;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -28,11 +30,14 @@ import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.apache.lucene.codecs.Codec;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.LeafReaderContext;
@ -48,25 +53,31 @@ import org.junit.Before;
public abstract class BackwardsCompatibilityTestBase extends LuceneTestCase {
protected final Version version;
private static final Version LATEST_PREVIOUS_MAJOR = getLatestPreviousMajorVersion();
protected final String indexPattern;
static final Set<String> OLD_VERSIONS;
protected static final Set<Version> BINARY_SUPPORTED_VERSIONS;
static {
String[] oldVersions =
new String[] {
"8.0.0", "8.0.0", "8.1.0", "8.1.0", "8.1.1", "8.1.1", "8.2.0", "8.2.0", "8.3.0", "8.3.0",
"8.3.1", "8.3.1", "8.4.0", "8.4.0", "8.4.1", "8.4.1", "8.5.0", "8.5.0", "8.5.1", "8.5.1",
"8.5.2", "8.5.2", "8.6.0", "8.6.0", "8.6.1", "8.6.1", "8.6.2", "8.6.2", "8.6.3", "8.6.3",
"8.7.0", "8.7.0", "8.8.0", "8.8.0", "8.8.1", "8.8.1", "8.8.2", "8.8.2", "8.9.0", "8.9.0",
"8.10.0", "8.10.0", "8.10.1", "8.10.1", "8.11.0", "8.11.0", "8.11.1", "8.11.1", "8.11.2",
"8.11.2", "8.11.3", "8.11.3", "9.0.0", "9.1.0", "9.2.0", "9.3.0", "9.4.0", "9.4.1",
"9.4.2", "9.5.0", "9.6.0", "9.7.0", "9.8.0", "9.9.0", "9.9.1", "9.9.2"
};
private static final Version LATEST_PREVIOUS_MAJOR = getLatestPreviousMajorVersion();
protected final Version version;
protected final String indexPattern;
static {
String name = "versions.txt";
try (LineNumberReader in =
new LineNumberReader(
IOUtils.getDecodingReader(
IOUtils.requireResourceNonNull(
BackwardsCompatibilityTestBase.class.getResourceAsStream(name), name),
StandardCharsets.UTF_8))) {
OLD_VERSIONS =
in.lines()
.filter(Predicate.not(String::isBlank))
.collect(Collectors.toCollection(LinkedHashSet::new));
} catch (IOException exception) {
throw new RuntimeException("failed to load resource", exception);
}
Set<Version> binaryVersions = new HashSet<>();
for (String version : oldVersions) {
for (String version : OLD_VERSIONS) {
try {
Version v = Version.parse(version);
assertTrue("Unsupported binary version: " + v, v.major >= Version.MIN_SUPPORTED_MAJOR - 1);

View File

@ -21,8 +21,16 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.LineNumberReader;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.lucene.index.CheckIndex;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexFormatTooOldException;
@ -36,274 +44,57 @@ import org.apache.lucene.tests.analysis.MockAnalyzer;
import org.apache.lucene.tests.store.BaseDirectoryWrapper;
import org.apache.lucene.tests.util.LuceneTestCase;
import org.apache.lucene.tests.util.TestUtil;
import org.apache.lucene.util.IOUtils;
@SuppressWarnings("deprecation")
public class TestAncientIndicesCompatibility extends LuceneTestCase {
static final Set<String> UNSUPPORTED_INDEXES;
static final String[] unsupportedNames = {
"1.9.0-cfs",
"1.9.0-nocfs",
"2.0.0-cfs",
"2.0.0-nocfs",
"2.1.0-cfs",
"2.1.0-nocfs",
"2.2.0-cfs",
"2.2.0-nocfs",
"2.3.0-cfs",
"2.3.0-nocfs",
"2.4.0-cfs",
"2.4.0-nocfs",
"2.4.1-cfs",
"2.4.1-nocfs",
"2.9.0-cfs",
"2.9.0-nocfs",
"2.9.1-cfs",
"2.9.1-nocfs",
"2.9.2-cfs",
"2.9.2-nocfs",
"2.9.3-cfs",
"2.9.3-nocfs",
"2.9.4-cfs",
"2.9.4-nocfs",
"3.0.0-cfs",
"3.0.0-nocfs",
"3.0.1-cfs",
"3.0.1-nocfs",
"3.0.2-cfs",
"3.0.2-nocfs",
"3.0.3-cfs",
"3.0.3-nocfs",
"3.1.0-cfs",
"3.1.0-nocfs",
"3.2.0-cfs",
"3.2.0-nocfs",
"3.3.0-cfs",
"3.3.0-nocfs",
"3.4.0-cfs",
"3.4.0-nocfs",
"3.5.0-cfs",
"3.5.0-nocfs",
"3.6.0-cfs",
"3.6.0-nocfs",
"3.6.1-cfs",
"3.6.1-nocfs",
"3.6.2-cfs",
"3.6.2-nocfs",
"4.0.0-cfs",
"4.0.0-cfs",
"4.0.0-nocfs",
"4.0.0.1-cfs",
"4.0.0.1-nocfs",
"4.0.0.2-cfs",
"4.0.0.2-nocfs",
"4.1.0-cfs",
"4.1.0-nocfs",
"4.2.0-cfs",
"4.2.0-nocfs",
"4.2.1-cfs",
"4.2.1-nocfs",
"4.3.0-cfs",
"4.3.0-nocfs",
"4.3.1-cfs",
"4.3.1-nocfs",
"4.4.0-cfs",
"4.4.0-nocfs",
"4.5.0-cfs",
"4.5.0-nocfs",
"4.5.1-cfs",
"4.5.1-nocfs",
"4.6.0-cfs",
"4.6.0-nocfs",
"4.6.1-cfs",
"4.6.1-nocfs",
"4.7.0-cfs",
"4.7.0-nocfs",
"4.7.1-cfs",
"4.7.1-nocfs",
"4.7.2-cfs",
"4.7.2-nocfs",
"4.8.0-cfs",
"4.8.0-nocfs",
"4.8.1-cfs",
"4.8.1-nocfs",
"4.9.0-cfs",
"4.9.0-nocfs",
"4.9.1-cfs",
"4.9.1-nocfs",
"4.10.0-cfs",
"4.10.0-nocfs",
"4.10.1-cfs",
"4.10.1-nocfs",
"4.10.2-cfs",
"4.10.2-nocfs",
"4.10.3-cfs",
"4.10.3-nocfs",
"4.10.4-cfs",
"4.10.4-nocfs",
"5x-with-4x-segments-cfs",
"5x-with-4x-segments-nocfs",
"5.0.0.singlesegment-cfs",
"5.0.0.singlesegment-nocfs",
"5.0.0-cfs",
"5.0.0-nocfs",
"5.1.0-cfs",
"5.1.0-nocfs",
"5.2.0-cfs",
"5.2.0-nocfs",
"5.2.1-cfs",
"5.2.1-nocfs",
"5.3.0-cfs",
"5.3.0-nocfs",
"5.3.1-cfs",
"5.3.1-nocfs",
"5.3.2-cfs",
"5.3.2-nocfs",
"5.4.0-cfs",
"5.4.0-nocfs",
"5.4.1-cfs",
"5.4.1-nocfs",
"5.5.0-cfs",
"5.5.0-nocfs",
"5.5.1-cfs",
"5.5.1-nocfs",
"5.5.2-cfs",
"5.5.2-nocfs",
"5.5.3-cfs",
"5.5.3-nocfs",
"5.5.4-cfs",
"5.5.4-nocfs",
"5.5.5-cfs",
"5.5.5-nocfs",
"6.0.0-cfs",
"6.0.0-nocfs",
"6.0.1-cfs",
"6.0.1-nocfs",
"6.1.0-cfs",
"6.1.0-nocfs",
"6.2.0-cfs",
"6.2.0-nocfs",
"6.2.1-cfs",
"6.2.1-nocfs",
"6.3.0-cfs",
"6.3.0-nocfs",
"6.4.0-cfs",
"6.4.0-nocfs",
"6.4.1-cfs",
"6.4.1-nocfs",
"6.4.2-cfs",
"6.4.2-nocfs",
"6.5.0-cfs",
"6.5.0-nocfs",
"6.5.1-cfs",
"6.5.1-nocfs",
"6.6.0-cfs",
"6.6.0-nocfs",
"6.6.1-cfs",
"6.6.1-nocfs",
"6.6.2-cfs",
"6.6.2-nocfs",
"6.6.3-cfs",
"6.6.3-nocfs",
"6.6.4-cfs",
"6.6.4-nocfs",
"6.6.5-cfs",
"6.6.5-nocfs",
"6.6.6-cfs",
"6.6.6-nocfs",
"7.0.0-cfs",
"7.0.0-nocfs",
"7.0.1-cfs",
"7.0.1-nocfs",
"7.1.0-cfs",
"7.1.0-nocfs",
"7.2.0-cfs",
"7.2.0-nocfs",
"7.2.1-cfs",
"7.2.1-nocfs",
"7.3.0-cfs",
"7.3.0-nocfs",
"7.3.1-cfs",
"7.3.1-nocfs",
"7.4.0-cfs",
"7.4.0-nocfs",
"7.5.0-cfs",
"7.5.0-nocfs",
"7.6.0-cfs",
"7.6.0-nocfs",
"7.7.0-cfs",
"7.7.0-nocfs",
"7.7.1-cfs",
"7.7.1-nocfs",
"7.7.2-cfs",
"7.7.2-nocfs",
"7.7.3-cfs",
"7.7.3-nocfs",
"8.0.0-cfs",
"8.0.0-nocfs",
"8.1.0-cfs",
"8.1.0-nocfs",
"8.1.1-cfs",
"8.1.1-nocfs",
"8.2.0-cfs",
"8.2.0-nocfs",
"8.3.0-cfs",
"8.3.0-nocfs",
"8.3.1-cfs",
"8.3.1-nocfs",
"8.4.0-cfs",
"8.4.0-nocfs",
"8.4.1-cfs",
"8.4.1-nocfs",
"8.5.0-cfs",
"8.5.0-nocfs",
"8.5.1-cfs",
"8.5.1-nocfs",
"8.5.2-cfs",
"8.5.2-nocfs",
"8.6.0-cfs",
"8.6.0-nocfs",
"8.6.1-cfs",
"8.6.1-nocfs",
"8.6.2-cfs",
"8.6.2-nocfs",
"8.6.3-cfs",
"8.6.3-nocfs",
"8.7.0-cfs",
"8.7.0-nocfs",
"8.8.0-cfs",
"8.8.0-nocfs",
"8.8.1-cfs",
"8.8.1-nocfs",
"8.8.2-cfs",
"8.8.2-nocfs",
"8.9.0-cfs",
"8.9.0-nocfs",
"8.10.0-cfs",
"8.10.0-nocfs",
"8.10.1-cfs",
"8.10.1-nocfs",
"8.11.0-cfs",
"8.11.0-nocfs",
"8.11.1-cfs",
"8.11.1-nocfs",
"8.11.2-cfs",
"8.11.2-nocfs",
"8.11.3-cfs",
"8.11.3-nocfs"
};
static {
String name = "unsupported_versions.txt";
Set<String> indices;
try (LineNumberReader in =
new LineNumberReader(
IOUtils.getDecodingReader(
IOUtils.requireResourceNonNull(
TestAncientIndicesCompatibility.class.getResourceAsStream(name), name),
StandardCharsets.UTF_8))) {
indices =
in.lines()
.filter(Predicate.not(String::isBlank))
.flatMap(version -> Stream.of(version + "-cfs", version + "-nocfs"))
.collect(Collectors.toCollection(LinkedHashSet::new));
} catch (IOException exception) {
throw new RuntimeException("failed to load resource", exception);
}
name = "unsupported_indices.txt";
try (LineNumberReader in =
new LineNumberReader(
IOUtils.getDecodingReader(
IOUtils.requireResourceNonNull(
TestAncientIndicesCompatibility.class.getResourceAsStream(name), name),
StandardCharsets.UTF_8))) {
indices.addAll(
in.lines()
.filter(Predicate.not(String::isBlank))
.collect(Collectors.toCollection(LinkedHashSet::new)));
} catch (IOException exception) {
throw new RuntimeException("failed to load resource", exception);
}
UNSUPPORTED_INDEXES = Collections.unmodifiableSet(indices);
}
/**
* This test checks that *only* IndexFormatTooOldExceptions are thrown when you open and operate
* on too old indexes!
*/
public void testUnsupportedOldIndexes() throws Exception {
for (int i = 0; i < unsupportedNames.length; i++) {
for (String version : UNSUPPORTED_INDEXES) {
if (VERBOSE) {
System.out.println("TEST: index " + unsupportedNames[i]);
System.out.println("TEST: index " + version);
}
Path oldIndexDir = createTempDir(unsupportedNames[i]);
TestUtil.unzip(
getDataInputStream("unsupported." + unsupportedNames[i] + ".zip"), oldIndexDir);
Path oldIndexDir = createTempDir(version);
TestUtil.unzip(getDataInputStream("unsupported." + version + ".zip"), oldIndexDir);
BaseDirectoryWrapper dir = newFSDirectory(oldIndexDir);
// don't checkindex, these are intentionally not supported
dir.setCheckIndexOnClose(false);
@ -312,7 +103,7 @@ public class TestAncientIndicesCompatibility extends LuceneTestCase {
IndexWriter writer = null;
try {
reader = DirectoryReader.open(dir);
fail("DirectoryReader.open should not pass for " + unsupportedNames[i]);
fail("DirectoryReader.open should not pass for " + version);
} catch (IndexFormatTooOldException e) {
if (e.getReason() != null) {
assertNull(e.getVersion());
@ -353,7 +144,7 @@ public class TestAncientIndicesCompatibility extends LuceneTestCase {
writer =
new IndexWriter(
dir, newIndexWriterConfig(new MockAnalyzer(random())).setCommitOnClose(false));
fail("IndexWriter creation should not pass for " + unsupportedNames[i]);
fail("IndexWriter creation should not pass for " + version);
} catch (IndexFormatTooOldException e) {
if (e.getReason() != null) {
assertNull(e.getVersion());
@ -406,7 +197,7 @@ public class TestAncientIndicesCompatibility extends LuceneTestCase {
CheckIndex checker = new CheckIndex(dir);
checker.setInfoStream(new PrintStream(bos, false, UTF_8));
CheckIndex.Status indexStatus = checker.checkIndex();
if (unsupportedNames[i].startsWith("8.")) {
if (version.startsWith("8.")) {
assertTrue(indexStatus.clean);
} else {
assertFalse(indexStatus.clean);

View File

@ -101,8 +101,6 @@ public class TestBasicBackwardsCompatibility extends BackwardsCompatibilityTestB
KnnFloatVectorField.createFieldType(3, VectorSimilarityFunction.COSINE);
private static final float[] KNN_VECTOR = {0.2f, -0.1f, 0.1f};
static final int MIN_BINARY_SUPPORTED_MAJOR = Version.MIN_SUPPORTED_MAJOR - 1;
/**
* A parameter constructor for {@link com.carrotsearch.randomizedtesting.RandomizedRunner}. See
* {@link #testVersionsFactory()} for details on the values provided to the framework.

View File

@ -62,7 +62,6 @@ public class TestBinaryBackwardsCompatibility extends BackwardsCompatibilityTest
@Nightly
public void testReadNMinusTwoCommit() throws IOException {
try (BaseDirectoryWrapper dir = newDirectory(directory)) {
IndexCommit commit = DirectoryReader.listCommits(dir).get(0);
StandardDirectoryReader.open(commit, MIN_BINARY_SUPPORTED_MAJOR, null).close();

View File

@ -0,0 +1,4 @@
5x-with-4x-segments-cfs
5x-with-4x-segments-nocfs
5.0.0.singlesegment-cfs
5.0.0.singlesegment-nocfs

View File

@ -0,0 +1,122 @@
1.9.0
2.0.0
2.1.0
2.2.0
2.3.0
2.4.0
2.4.1
2.9.0
2.9.1
2.9.2
2.9.3
2.9.4
3.0.0
3.0.1
3.0.2
3.0.3
3.1.0
3.2.0
3.3.0
3.4.0
3.5.0
3.6.0
3.6.1
3.6.2
4.0.0
4.0.0.1
4.0.0.2
4.1.0
4.2.0
4.2.1
4.3.0
4.3.1
4.4.0
4.5.0
4.5.1
4.6.0
4.6.1
4.7.0
4.7.1
4.7.2
4.8.0
4.8.1
4.9.0
4.9.1
4.10.0
4.10.1
4.10.2
4.10.3
4.10.4
5.0.0
5.1.0
5.2.0
5.2.1
5.3.0
5.3.1
5.3.2
5.4.0
5.4.1
5.5.0
5.5.1
5.5.2
5.5.3
5.5.4
5.5.5
6.0.0
6.0.1
6.1.0
6.2.0
6.2.1
6.3.0
6.4.0
6.4.1
6.4.2
6.5.0
6.5.1
6.6.0
6.6.1
6.6.2
6.6.3
6.6.4
6.6.5
6.6.6
7.0.0
7.0.1
7.1.0
7.2.0
7.2.1
7.3.0
7.3.1
7.4.0
7.5.0
7.6.0
7.7.0
7.7.1
7.7.2
7.7.3
8.0.0
8.1.0
8.1.1
8.2.0
8.3.0
8.3.1
8.4.0
8.4.1
8.5.0
8.5.1
8.5.2
8.6.0
8.6.1
8.6.2
8.6.3
8.7.0
8.8.0
8.8.1
8.8.2
8.9.0
8.10.0
8.10.1
8.11.0
8.11.1
8.11.2
8.11.3

View File

@ -0,0 +1,40 @@
8.0.0
8.1.0
8.1.1
8.2.0
8.3.0
8.3.1
8.4.0
8.4.1
8.5.0
8.5.1
8.5.2
8.6.0
8.6.1
8.6.2
8.6.3
8.7.0
8.8.0
8.8.1
8.8.2
8.9.0
8.10.0
8.10.1
8.11.0
8.11.1
8.11.2
8.11.3
9.0.0
9.1.0
9.2.0
9.3.0
9.4.0
9.4.1
9.4.2
9.5.0
9.6.0
9.7.0
9.8.0
9.9.0
9.9.1
9.9.2